diff --git a/src/Makefile b/src/Makefile index 11ad62a..c97de40 100644 --- a/src/Makefile +++ b/src/Makefile @@ -55,7 +55,7 @@ TARGET = $(OBJDIR)/sd2snes # List C source files here. (C dependencies are automatically generated.) -SRC = main.c ff.c ccsbcs.c clock.c uart.c power.c led.c timer.c printf.c spi.c fileops.c rtc.c fpga.c fpga_spi.c snes.c smc.c memory.c filetypes.c faulthandler.c sort.c crc32.c cic.c cli.c xmodem.c irq.c rle.c sdnative.c msu1.c crc16.c sysinfo.c cfg.c +SRC = main.c ff.c ccsbcs.c clock.c uart.c power.c led.c timer.c printf.c spi.c fileops.c rtc.c fpga.c fpga_spi.c snes.c smc.c memory.c filetypes.c faulthandler.c sort.c crc32.c cic.c cli.c xmodem.c irq.c rle.c sdnative.c msu1.c crc16.c sysinfo.c cfg.c tests.c # usbcontrol.c usb_hid.c usbhw_lpc.c usbinit.c usbstdreq.c @@ -198,7 +198,7 @@ ALL_ASFLAGS = -I. -x assembler-with-cpp $(ASFLAGS) $(CDEFS) # Default target. all: build -build: cfgware.h elf bin hex +build: snesboot.h cfgware.h elf bin hex $(E) " SIZE $(TARGET).elf" $(Q)$(ELFSIZE)|grep -v debug cp $(TARGET).bin $(OBJDIR)/firmware.img @@ -218,13 +218,13 @@ sym: $(TARGET).sym program: build utils/lpcchksum $(TARGET).bin - openocd -f openocd-usb.cfg -f lpc1754.cfg -f flash.cfg + openocd -f interface/olimex-arm-usb-ocd.cfg -f lpc1754.cfg -f flash.cfg debug: build - openocd -f openocd-usb.cfg -f lpc1754.cfg + openocd -f interface/olimex-arm-usb-ocd.cfg -f lpc1754.cfg reset: - openocd -f openocd-usb.cfg -f lpc1754.cfg -f reset.cfg + openocd -f interface/olimex-arm-usb-ocd.cfg -f lpc1754.cfg -f reset.cfg # Display size of file. HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex @@ -234,12 +234,22 @@ ELFSIZE = $(SIZE) -A $(TARGET).elf # Generate cfgware.h cfgware.h: $(OBJDIR)/fpga_rle.bit $(E) " BIN2H $@" - $(Q) $(BIN2H) $< $@ + $(Q) $(BIN2H) $< $@ cfgware -$(OBJDIR)/fpga_rle.bit: sd2sneslite.bit +$(OBJDIR)/fpga_rle.bit: ../verilog/sd2sneslite/main.bit $(E) " RLE $@" $(Q) $(RLE) $< $@ +#generate snesboot.h +snesboot.h: $(OBJDIR)/snesboot.rle + $(E) " BIN2H $@" + $(Q) $(BIN2H) $< $@ bootrle + +$(OBJDIR)/snesboot.rle: ../snes/boot/menu.bin + $(E) " RLE $@" + $(Q) $(RLE) $< $@ + + # Generate autoconf.h from config .PRECIOUS : $(OBJDIR)/autoconf.h $(OBJDIR)/autoconf.h: $(CONFIG) | $(OBJDIR) diff --git a/src/bits.h b/src/bits.h index 5055737..1b9ad26 100644 --- a/src/bits.h +++ b/src/bits.h @@ -6,16 +6,16 @@ /* CM3 bit-band access macro - no error checks! */ #define BITBAND(addr,bit) \ - (*((volatile unsigned long *)( \ - ((unsigned long)&(addr) & 0x01ffffff)*32 + \ - (bit)*4 + 0x02000000 + ((unsigned long)&(addr) & 0xfe000000) \ - ))) + (*((volatile unsigned long *)( \ + ((unsigned long)&(addr) & 0x01ffffff)*32 + \ + (bit)*4 + 0x02000000 + ((unsigned long)&(addr) & 0xfe000000) \ + ))) #define BITBAND_OFF(addr,offset,bit) \ - (*((volatile unsigned long *)( \ - (((unsigned long)&(addr) + offset) & 0x01ffffff)*32 + \ - (bit)*4 + 0x02000000 + (((unsigned long)&(addr) + offset) & 0xfe000000) \ - ))) + (*((volatile unsigned long *)( \ + (((unsigned long)&(addr) + offset) & 0x01ffffff)*32 + \ + (bit)*4 + 0x02000000 + (((unsigned long)&(addr) + offset) & 0xfe000000) \ + ))) #endif diff --git a/src/bootldr/bits.h b/src/bootldr/bits.h index 5055737..1fe3c1c 100644 --- a/src/bootldr/bits.h +++ b/src/bootldr/bits.h @@ -4,18 +4,18 @@ /* The classic macro */ #define BV(x) (1<<(x)) -/* CM3 bit-band access macro - no error checks! */ -#define BITBAND(addr,bit) \ - (*((volatile unsigned long *)( \ - ((unsigned long)&(addr) & 0x01ffffff)*32 + \ - (bit)*4 + 0x02000000 + ((unsigned long)&(addr) & 0xfe000000) \ - ))) +/* CM3 bit-bang access macro - no error checks! */ +#define BITBANG(addr,bit) \ + (*((volatile unsigned long *)( \ + ((unsigned long)&(addr) & 0x01ffffff)*32 + \ + (bit)*4 + 0x02000000 + ((unsigned long)&(addr) & 0xfe000000) \ + ))) -#define BITBAND_OFF(addr,offset,bit) \ - (*((volatile unsigned long *)( \ - (((unsigned long)&(addr) + offset) & 0x01ffffff)*32 + \ - (bit)*4 + 0x02000000 + (((unsigned long)&(addr) + offset) & 0xfe000000) \ - ))) +#define BITBANG_OFF(addr,offset,bit) \ + (*((volatile unsigned long *)( \ + (((unsigned long)&(addr) + offset) & 0x01ffffff)*32 + \ + (bit)*4 + 0x02000000 + (((unsigned long)&(addr) + offset) & 0xfe000000) \ + ))) #endif diff --git a/src/bootldr/ccsbcs.c b/src/bootldr/ccsbcs.c index eb0ab4e..75f4ecd 100644 --- a/src/bootldr/ccsbcs.c +++ b/src/bootldr/ccsbcs.c @@ -31,463 +31,484 @@ #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 +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, 0xO650, 0x2248, - 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +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, 0xO650, 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 +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 == 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 +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 +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 +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 +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 +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 == 858 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP858(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, 0x2550, 0x00A2, 0x00A5, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, - 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x20AC, 0x00CD, 0x00CE, - 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00C6, 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 +const WCHAR Tbl[] = /* CP858(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, 0x2550, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x20AC, 0x00CD, 0x00CE, + 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00C6, 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 == 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 +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 == 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 +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 == 874 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP874(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, - 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, - 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, - 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F, - 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, - 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, - 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, - 0x0E38, 0x0E39, 0x0E3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E3F, - 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, - 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, - 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, - 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000, 0x0000, 0x0000 +const WCHAR Tbl[] = /* CP874(0x80-0xFF) to Unicode conversion table */ +{ + 0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, + 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, + 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, + 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F, + 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, + 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, + 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, + 0x0E38, 0x0E39, 0x0E3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E3F, + 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, + 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, + 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, + 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000, 0x0000, 0x0000 }; #elif _CODE_PAGE == 1250 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP1250(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, - 0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A, - 0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B, - 0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C, - 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, - 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, - 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, - 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, - 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, - 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, - 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, - 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9 +const WCHAR Tbl[] = /* CP1250(0x80-0xFF) to Unicode conversion table */ +{ + 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, + 0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A, + 0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B, + 0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C, + 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, + 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, + 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, + 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, + 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, + 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, + 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, + 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9 }; #elif _CODE_PAGE == 1251 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP1251(0x80-0xFF) to Unicode conversion table */ - 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, - 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, - 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x2111, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, - 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, - 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407, - 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, - 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457, - 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, - 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, - 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F +const WCHAR Tbl[] = /* CP1251(0x80-0xFF) to Unicode conversion table */ +{ + 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, + 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, + 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2111, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, + 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, + 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407, + 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, + 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457, + 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, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F }; #elif _CODE_PAGE == 1252 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, - 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF +const WCHAR Tbl[] = /* CP1252(0x80-0xFF) to Unicode conversion table */ +{ + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF }; #elif _CODE_PAGE == 1253 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP1253(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x0000, 0x2030, 0x0000, 0x2039, 0x000C, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x0000, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7, - 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, - 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, - 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, - 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, - 0x03A8, 0x03A9, 0x03AA, 0x03AD, 0x03AC, 0x03AD, 0x03AE, 0x03AF, - 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, - 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, - 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, - 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000 +const WCHAR Tbl[] = /* CP1253(0x80-0xFF) to Unicode conversion table */ +{ + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x0000, 0x2030, 0x0000, 0x2039, 0x000C, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x0000, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7, + 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, + 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, + 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, + 0x03A8, 0x03A9, 0x03AA, 0x03AD, 0x03AC, 0x03AD, 0x03AE, 0x03AF, + 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, + 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, + 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000 }; #elif _CODE_PAGE == 1254 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP1254(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x210A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, - 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00BD, 0x00DC, 0x0130, 0x015E, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF +const WCHAR Tbl[] = /* CP1254(0x80-0xFF) to Unicode conversion table */ +{ + 0x20AC, 0x0000, 0x210A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00BD, 0x00DC, 0x0130, 0x015E, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF }; #elif _CODE_PAGE == 1255 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP1255(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, - 0x05B8, 0x05B9, 0x0000, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, - 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3, - 0x05F4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 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, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000 +const WCHAR Tbl[] = /* CP1255(0x80-0xFF) to Unicode conversion table */ +{ + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, + 0x05B8, 0x05B9, 0x0000, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, + 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3, + 0x05F4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 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, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000 }; #elif _CODE_PAGE == 1256 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP1256(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, - 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA, - 0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F, - 0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, - 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, - 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7, - 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0640, 0x0642, 0x0643, - 0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF, - 0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7, - 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2 +const WCHAR Tbl[] = /* CP1256(0x80-0xFF) to Unicode conversion table */ +{ + 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, + 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA, + 0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F, + 0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, + 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, + 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7, + 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0640, 0x0642, 0x0643, + 0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF, + 0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7, + 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2 } #elif _CODE_PAGE == 1257 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP1257(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, - 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x00AF, 0x02DB, 0x0000, - 0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x0000, 0x00A6, 0x00A7, - 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, - 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, - 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, - 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, - 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, - 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, - 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, - 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, - 0x0173, 0x014E, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9 +const WCHAR Tbl[] = /* CP1257(0x80-0xFF) to Unicode conversion table */ +{ + 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, + 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x00AF, 0x02DB, 0x0000, + 0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x0000, 0x00A6, 0x00A7, + 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, + 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, + 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, + 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, + 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, + 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, + 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, + 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, + 0x0173, 0x014E, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9 }; #elif _CODE_PAGE == 1258 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP1258(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0x0000, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF, - 0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF, - 0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF +const WCHAR Tbl[] = /* CP1258(0x80-0xFF) to Unicode conversion table */ +{ + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0000, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF, + 0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF, + 0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF }; #endif @@ -498,43 +519,54 @@ const WCHAR Tbl[] = { /* CP1258(0x80-0xFF) to Unicode conversion table */ #endif -WCHAR ff_convert ( /* Converted character, Returns zero on error */ - WCHAR src, /* Character code to be converted */ - UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */ +WCHAR ff_convert ( /* Converted character, Returns zero on error */ + WCHAR src, /* Character code to be converted */ + UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */ ) { - WCHAR c; + WCHAR c; - if (src < 0x80) { /* ASCII */ - c = src; + if ( src < 0x80 ) /* ASCII */ + { + c = src; - } else { - if (dir) { /* OEMCP to Unicode */ - c = (src >= 0x100) ? 0 : Tbl[src - 0x80]; + } + else + { + if ( dir ) /* OEMCP to Unicode */ + { + c = ( src >= 0x100 ) ? 0 : Tbl[src - 0x80]; - } else { /* Unicode to OEMCP */ - for (c = 0; c < 0x80; c++) { - if (src == Tbl[c]) break; - } - c = (c + 0x80) & 0xFF; - } - } + } + else /* Unicode to OEMCP */ + { + for ( c = 0; c < 0x80; c++ ) + { + if ( src == Tbl[c] ) + { + break; + } + } - return c; + c = ( c + 0x80 ) & 0xFF; + } + } + + return c; } -WCHAR ff_wtoupper ( /* Upper converted character */ - WCHAR chr /* Input character */ +WCHAR ff_wtoupper ( /* Upper converted character */ + WCHAR chr /* Input character */ ) { - static const WCHAR tbl_lower[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x0FF, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, 0x192, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0 }; - static const WCHAR tbl_upper[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, 0x191, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0 }; - int i; + static const WCHAR tbl_lower[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x0FF, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, 0x192, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0 }; + static const WCHAR tbl_upper[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, 0x191, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0 }; + int i; - for (i = 0; tbl_lower[i] && chr != tbl_lower[i]; i++) ; + for ( i = 0; tbl_lower[i] && chr != tbl_lower[i]; i++ ) ; - return tbl_lower[i] ? tbl_upper[i] : chr; + return tbl_lower[i] ? tbl_upper[i] : chr; } diff --git a/src/bootldr/clock.c b/src/bootldr/clock.c index 8bd7914..38de978 100644 --- a/src/bootldr/clock.c +++ b/src/bootldr/clock.c @@ -7,101 +7,116 @@ #include "bits.h" #include "uart.h" -void clock_disconnect() { - disconnectPLL0(); - disablePLL0(); +void clock_disconnect() +{ + disconnectPLL0(); + disablePLL0(); } -void clock_init() { +void clock_init() +{ -/* set flash access time to 6 clks (safe setting) */ - setFlashAccessTime(6); + /* set flash access time to 6 clks (safe setting) */ + setFlashAccessTime( 6 ); -/* setup PLL0 for ~44100*256*8 Hz - Base clock: 12MHz - Multiplier: 429 - Pre-Divisor: 19 - Divisor: 6 - (want: 90316800, get: 90315789.47) - -> DAC freq = 44099.5 Hz - -> FPGA freq = 11289473.7Hz - First, disable and disconnect PLL0. -*/ -// clock_disconnect(); + /* setup PLL0 for ~44100*256*8 Hz + Base clock: 12MHz + Multiplier: 429 + Pre-Divisor: 19 + Divisor: 6 + (want: 90316800, get: 90315789.47) + -> DAC freq = 44099.5 Hz + -> FPGA freq = 11289473.7Hz + First, disable and disconnect PLL0. + */ + // clock_disconnect(); -/* PLL is disabled and disconnected. setup PCLK NOW as it cannot be changed - reliably with PLL0 connected. - see: - http://ics.nxp.com/support/documents/microcontrollers/pdf/errata.lpc1754.pdf -*/ + /* PLL is disabled and disconnected. setup PCLK NOW as it cannot be changed + reliably with PLL0 connected. + see: + http://ics.nxp.com/support/documents/microcontrollers/pdf/errata.lpc1754.pdf + */ -/* continue with PLL0 setup: - enable the xtal oscillator and wait for it to become stable - set the oscillator as clk source for PLL0 - set PLL0 multiplier+predivider - enable PLL0 - set CCLK divider - wait for PLL0 to lock - connect PLL0 - done - */ - enableMainOsc(); - setClkSrc(CLKSRC_MAINOSC); - setPLL0MultPrediv(12, 1); - enablePLL0(); - setCCLKDiv(3); - connectPLL0(); + /* continue with PLL0 setup: + enable the xtal oscillator and wait for it to become stable + set the oscillator as clk source for PLL0 + set PLL0 multiplier+predivider + enable PLL0 + set CCLK divider + wait for PLL0 to lock + connect PLL0 + done + */ + enableMainOsc(); + setClkSrc( CLKSRC_MAINOSC ); + setPLL0MultPrediv( 12, 1 ); + enablePLL0(); + setCCLKDiv( 3 ); + connectPLL0(); } -void setFlashAccessTime(uint8_t clocks) { - LPC_SC->FLASHCFG=FLASHTIM(clocks); +void setFlashAccessTime( uint8_t clocks ) +{ + LPC_SC->FLASHCFG = FLASHTIM( clocks ); } -void setPLL0MultPrediv(uint16_t mult, uint8_t prediv) { - LPC_SC->PLL0CFG=PLL_MULT(mult) | PLL_PREDIV(prediv); - PLL0feed(); +void setPLL0MultPrediv( uint16_t mult, uint8_t prediv ) +{ + LPC_SC->PLL0CFG = PLL_MULT( mult ) | PLL_PREDIV( prediv ); + PLL0feed(); } -void enablePLL0() { - LPC_SC->PLL0CON |= PLLE0; - PLL0feed(); +void enablePLL0() +{ + LPC_SC->PLL0CON |= PLLE0; + PLL0feed(); } -void disablePLL0() { - LPC_SC->PLL0CON &= ~PLLE0; - PLL0feed(); +void disablePLL0() +{ + LPC_SC->PLL0CON &= ~PLLE0; + PLL0feed(); } -void connectPLL0() { - while(!(LPC_SC->PLL0STAT&PLOCK0)); - LPC_SC->PLL0CON |= PLLC0; - PLL0feed(); +void connectPLL0() +{ + while ( !( LPC_SC->PLL0STAT & PLOCK0 ) ); + + LPC_SC->PLL0CON |= PLLC0; + PLL0feed(); } -void disconnectPLL0() { - LPC_SC->PLL0CON &= ~PLLC0; - PLL0feed(); +void disconnectPLL0() +{ + LPC_SC->PLL0CON &= ~PLLC0; + PLL0feed(); } -void setCCLKDiv(uint8_t div) { - LPC_SC->CCLKCFG=CCLK_DIV(div); +void setCCLKDiv( uint8_t div ) +{ + LPC_SC->CCLKCFG = CCLK_DIV( div ); } -void enableMainOsc() { - LPC_SC->SCS=OSCEN; - while(!(LPC_SC->SCS&OSCSTAT)); +void enableMainOsc() +{ + LPC_SC->SCS = OSCEN; + + while ( !( LPC_SC->SCS & OSCSTAT ) ); } -void disableMainOsc() { - LPC_SC->SCS=0; +void disableMainOsc() +{ + LPC_SC->SCS = 0; } -void PLL0feed() { - LPC_SC->PLL0FEED=0xaa; - LPC_SC->PLL0FEED=0x55; +void PLL0feed() +{ + LPC_SC->PLL0FEED = 0xaa; + LPC_SC->PLL0FEED = 0x55; } -void setClkSrc(uint8_t src) { - LPC_SC->CLKSRCSEL=src; +void setClkSrc( uint8_t src ) +{ + LPC_SC->CLKSRCSEL = src; } diff --git a/src/bootldr/clock.h b/src/bootldr/clock.h index 56be21a..9a35db6 100644 --- a/src/bootldr/clock.h +++ b/src/bootldr/clock.h @@ -18,62 +18,62 @@ #define PCLK_CCLK2(x) (2<<(x)) /* shift values for use with PCLKSEL0 */ -#define PCLK_WDT (0) -#define PCLK_TIMER0 (2) -#define PCLK_TIMER1 (4) -#define PCLK_UART0 (6) -#define PCLK_UART1 (8) -#define PCLK_PWM1 (12) -#define PCLK_I2C0 (14) -#define PCLK_SPI (16) -#define PCLK_SSP1 (20) -#define PCLK_DAC (22) -#define PCLK_ADC (24) -#define PCLK_CAN1 (26) -#define PCLK_CAN2 (28) -#define PCLK_ACF (30) +#define PCLK_WDT (0) +#define PCLK_TIMER0 (2) +#define PCLK_TIMER1 (4) +#define PCLK_UART0 (6) +#define PCLK_UART1 (8) +#define PCLK_PWM1 (12) +#define PCLK_I2C0 (14) +#define PCLK_SPI (16) +#define PCLK_SSP1 (20) +#define PCLK_DAC (22) +#define PCLK_ADC (24) +#define PCLK_CAN1 (26) +#define PCLK_CAN2 (28) +#define PCLK_ACF (30) /* shift values for use with PCLKSEL1 */ -#define PCLK_QEI (0) -#define PCLK_GPIOINT (2) -#define PCLK_PCB (4) -#define PCLK_I2C1 (6) -#define PCLK_SSP0 (10) -#define PCLK_TIMER2 (12) +#define PCLK_QEI (0) +#define PCLK_GPIOINT (2) +#define PCLK_PCB (4) +#define PCLK_I2C1 (6) +#define PCLK_SSP0 (10) +#define PCLK_TIMER2 (12) #define PCLK_TIMER3 (14) -#define PCLK_UART2 (16) -#define PCLK_UART3 (18) -#define PCLK_I2C2 (20) -#define PCLK_I2S (22) -#define PCLK_RIT (26) -#define PCLK_SYSCON (28) -#define PCLK_MC (30) +#define PCLK_UART2 (16) +#define PCLK_UART3 (18) +#define PCLK_I2C2 (20) +#define PCLK_I2S (22) +#define PCLK_RIT (26) +#define PCLK_SYSCON (28) +#define PCLK_MC (30) -void clock_disconnect(void); +void clock_disconnect( void ); -void clock_init(void); +void clock_init( void ); -void setFlashAccessTime(uint8_t clocks); +void setFlashAccessTime( uint8_t clocks ); -void setPLL0MultPrediv(uint16_t mult, uint8_t prediv); +void setPLL0MultPrediv( uint16_t mult, uint8_t prediv ); -void enablePLL0(void); +void enablePLL0( void ); -void disablePLL0(void); +void disablePLL0( void ); -void connectPLL0(void); +void connectPLL0( void ); -void disconnectPLL0(void); +void disconnectPLL0( void ); -void setCCLKDiv(uint8_t div); +void setCCLKDiv( uint8_t div ); -void enableMainOsc(void); +void enableMainOsc( void ); -void disableMainOsc(void); +void disableMainOsc( void ); -void PLL0feed(void); +void PLL0feed( void ); -void setClkSrc(uint8_t src); +void setClkSrc( uint8_t src ); #endif diff --git a/src/bootldr/config.h b/src/bootldr/config.h index 429fcc5..797e9de 100644 --- a/src/bootldr/config.h +++ b/src/bootldr/config.h @@ -27,12 +27,12 @@ #define IN_AHBRAM __attribute__ ((section(".ahbram"))) #define SD_DT_INT_SETUP() do {\ - BITBAND(LPC_GPIOINT->IO2IntEnR, SD_DT_BIT) = 1;\ - BITBAND(LPC_GPIOINT->IO2IntEnF, SD_DT_BIT) = 1;\ - } while(0) + BITBANG(LPC_GPIOINT->IO2IntEnR, SD_DT_BIT) = 1;\ + BITBANG(LPC_GPIOINT->IO2IntEnF, SD_DT_BIT) = 1;\ + } while(0) -#define SD_CHANGE_DETECT (BITBAND(LPC_GPIOINT->IO2IntStatR, SD_DT_BIT)\ - |BITBAND(LPC_GPIOINT->IO2IntStatF, SD_DT_BIT)) +#define SD_CHANGE_DETECT (BITBANG(LPC_GPIOINT->IO2IntStatR, SD_DT_BIT)\ + |BITBANG(LPC_GPIOINT->IO2IntStatF, SD_DT_BIT)) #define SD_CHANGE_CLR() do {LPC_GPIOINT->IO2IntClr = BV(SD_DT_BIT);} while(0) @@ -41,15 +41,15 @@ #define SD_WP_REG LPC_GPIO0 #define SD_WP_BIT 6 -#define SDCARD_DETECT (!(BITBAND(SD_DT_REG->FIOPIN, SD_DT_BIT))) -#define SDCARD_WP (BITBAND(SD_WP_REG->FIOPIN, SD_WP_BIT)) +#define SDCARD_DETECT (!(BITBANG(SD_DT_REG->FIOPIN, SD_DT_BIT))) +#define SDCARD_WP (BITBANG(SD_WP_REG->FIOPIN, SD_WP_BIT)) #define SD_SUPPLY_VOLTAGE (1L<<21) /* 3.3V - 3.4V */ #define CONFIG_SD_BLOCKTRANSFER 1 #define CONFIG_SD_AUTO_RETRIES 10 // #define SD_CHANGE_VECT #define CONFIG_SD_DATACRC 1 -#define CONFIG_UART_NUM 3 +#define CONFIG_UART_NUM 3 // #define CONFIG_CPU_FREQUENCY 90315789 #define CONFIG_CPU_FREQUENCY (96000000L) //#define CONFIG_CPU_FREQUENCY 46000000 diff --git a/src/bootldr/crc.h b/src/bootldr/crc.h index 34e0053..093c327 100644 --- a/src/bootldr/crc.h +++ b/src/bootldr/crc.h @@ -1,9 +1,9 @@ #ifndef CRC_H #define CRC_H -uint8_t crc7update(uint8_t crc, uint8_t data); -uint16_t crc_xmodem_update(uint16_t crc, uint8_t data); -uint16_t crc_xmodem_block(uint16_t crc, const uint8_t *data, uint32_t length); +uint8_t crc7update( uint8_t crc, uint8_t data ); +uint16_t crc_xmodem_update( uint16_t crc, uint8_t data ); +uint16_t crc_xmodem_block( uint16_t crc, const uint8_t *data, uint32_t length ); // AVR-libc compatibility #define _crc_xmodem_update(crc,data) crc_xmodem_update(crc,data) diff --git a/src/bootldr/crc32.c b/src/bootldr/crc32.c index 42ece34..afabc4d 100644 --- a/src/bootldr/crc32.c +++ b/src/bootldr/crc32.c @@ -26,17 +26,19 @@ * \param data_len The width of \a data expressed in number of bits. * \return The reflected data. ******************************************************************************/ -uint32_t crc_reflect(uint32_t data, size_t data_len) +uint32_t crc_reflect( uint32_t data, size_t data_len ) { unsigned int i; uint32_t ret; ret = data & 0x01; - for (i = 1; i < data_len; i++) + + for ( i = 1; i < data_len; i++ ) { data >>= 1; - ret = (ret << 1) | (data & 0x01); + ret = ( ret << 1 ) | ( data & 0x01 ); } + return ret; } @@ -49,23 +51,31 @@ uint32_t crc_reflect(uint32_t data, size_t data_len) * \param data_len Number of bytes in the \a data buffer. * \return The updated crc value. *****************************************************************************/ -uint32_t crc32_update(uint32_t crc, const unsigned char data) +uint32_t crc32_update( uint32_t crc, const unsigned char data ) { unsigned int i; uint32_t bit; unsigned char c; c = data; - for (i = 0x01; i & 0xff; i <<= 1) { + + for ( i = 0x01; i & 0xff; i <<= 1 ) + { bit = crc & 0x80000000; - if (c & i) { + + if ( c & i ) + { bit = !bit; } + crc <<= 1; - if (bit) { + + if ( bit ) + { crc ^= 0x04c11db7; } } + return crc & 0xffffffff; } diff --git a/src/bootldr/crc32.h b/src/bootldr/crc32.h index fbc5e55..2893a95 100644 --- a/src/bootldr/crc32.h +++ b/src/bootldr/crc32.h @@ -42,14 +42,14 @@ extern "C" { * \param data_len The width of \a data expressed in number of bits. * \return The reflected data. *****************************************************************************/ -uint32_t crc_reflect(uint32_t data, size_t data_len); +uint32_t crc_reflect( uint32_t data, size_t data_len ); /** * Calculate the initial crc value. * * \return The initial crc value. *****************************************************************************/ -static inline uint32_t crc_init(void) +static inline uint32_t crc_init( void ) { return 0xffffffff; } @@ -62,7 +62,7 @@ static inline uint32_t crc_init(void) * \param data_len Number of bytes in the \a data buffer. * \return The updated crc value. *****************************************************************************/ -uint32_t crc32_update(uint32_t crc, const unsigned char data); +uint32_t crc32_update( uint32_t crc, const unsigned char data ); /** * Calculate the final crc value. @@ -70,9 +70,9 @@ uint32_t crc32_update(uint32_t crc, const unsigned char data); * \param crc The current crc value. * \return The final crc value. *****************************************************************************/ -static inline uint32_t crc_finalize(uint32_t crc) +static inline uint32_t crc_finalize( uint32_t crc ) { - return crc_reflect(crc, 32) ^ 0xffffffff; + return crc_reflect( crc, 32 ) ^ 0xffffffff; } diff --git a/src/bootldr/diskio.h b/src/bootldr/diskio.h index dde29bd..3f53c37 100644 --- a/src/bootldr/diskio.h +++ b/src/bootldr/diskio.h @@ -4,8 +4,8 @@ #ifndef _DISKIO -#define _READONLY 0 /* 1: Remove write functions */ -#define _USE_IOCTL 1 /* 1: Use disk_ioctl fucntion */ +#define _READONLY 0 /* 1: Remove write functions */ +#define _USE_IOCTL 1 /* 1: Use disk_ioctl fucntion */ #include @@ -13,15 +13,16 @@ /* Status of Disk Functions */ -typedef BYTE DSTATUS; +typedef BYTE DSTATUS; /* Results of Disk Functions */ -typedef enum { - RES_OK = 0, /* 0: Successful */ - RES_ERROR, /* 1: R/W Error */ - RES_WRPRT, /* 2: Write Protected */ - RES_NOTRDY, /* 3: Not Ready */ - RES_PARERR /* 4: Invalid Parameter */ +typedef enum +{ + RES_OK = 0, /* 0: Successful */ + RES_ERROR, /* 1: R/W Error */ + RES_WRPRT, /* 2: Write Protected */ + RES_NOTRDY, /* 3: Not Ready */ + RES_PARERR /* 4: Invalid Parameter */ } DRESULT; /** @@ -35,12 +36,13 @@ typedef enum { * This is the struct returned in the data buffer when disk_getinfo * is called with page=0. */ -typedef struct { - uint8_t validbytes; - uint8_t maxpage; - uint8_t disktype; - uint8_t sectorsize; /* divided by 256 */ - uint32_t sectorcount; /* 2 TB should be enough... (512 byte sectors) */ +typedef struct +{ + uint8_t validbytes; + uint8_t maxpage; + uint8_t disktype; + uint8_t sectorsize; /* divided by 256 */ + uint32_t sectorcount; /* 2 TB should be enough... (512 byte sectors) */ } diskinfo0_t; @@ -48,17 +50,17 @@ typedef struct { /*---------------------------------------*/ /* Prototypes for disk control functions */ -int assign_drives (int, int); -DSTATUS disk_initialize (BYTE); -DSTATUS disk_status (BYTE); -DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE); -#if _READONLY == 0 -DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE); +int assign_drives ( int, int ); +DSTATUS disk_initialize ( BYTE ); +DSTATUS disk_status ( BYTE ); +DRESULT disk_read ( BYTE, BYTE *, DWORD, BYTE ); +#if _READONLY == 0 +DRESULT disk_write ( BYTE, const BYTE *, DWORD, BYTE ); #endif #define disk_ioctl(a,b,c) RES_OK -#define get_fattime() (0) +#define get_fattime() (0) -void disk_init(void); +void disk_init( void ); /* Will be set to DISK_ERROR if any access on the card fails */ enum diskstates { DISK_CHANGED = 0, DISK_REMOVED, DISK_OK, DISK_ERROR }; @@ -80,39 +82,39 @@ extern volatile enum diskstates disk_state; /* Disk Status Bits (DSTATUS) */ -#define STA_NOINIT 0x01 /* Drive not initialized */ -#define STA_NODISK 0x02 /* No medium in the drive */ -#define STA_PROTECT 0x04 /* Write protected */ +#define STA_NOINIT 0x01 /* Drive not initialized */ +#define STA_NODISK 0x02 /* No medium in the drive */ +#define STA_PROTECT 0x04 /* Write protected */ /* Command code for disk_ioctrl fucntion */ /* Generic command (defined for FatFs) */ -#define CTRL_SYNC 0 /* Flush disk cache (for write functions) */ -#define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */ -#define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */ -#define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */ -#define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */ +#define CTRL_SYNC 0 /* Flush disk cache (for write functions) */ +#define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */ +#define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */ +#define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */ +#define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */ /* Generic command */ -#define CTRL_POWER 5 /* Get/Set power status */ -#define CTRL_LOCK 6 /* Lock/Unlock media removal */ -#define CTRL_EJECT 7 /* Eject media */ +#define CTRL_POWER 5 /* Get/Set power status */ +#define CTRL_LOCK 6 /* Lock/Unlock media removal */ +#define CTRL_EJECT 7 /* Eject media */ /* MMC/SDC specific ioctl command */ -#define MMC_GET_TYPE 10 /* Get card type */ -#define MMC_GET_CSD 11 /* Get CSD */ -#define MMC_GET_CID 12 /* Get CID */ -#define MMC_GET_OCR 13 /* Get OCR */ -#define MMC_GET_SDSTAT 14 /* Get SD status */ +#define MMC_GET_TYPE 10 /* Get card type */ +#define MMC_GET_CSD 11 /* Get CSD */ +#define MMC_GET_CID 12 /* Get CID */ +#define MMC_GET_OCR 13 /* Get OCR */ +#define MMC_GET_SDSTAT 14 /* Get SD status */ /* ATA/CF specific ioctl command */ -#define ATA_GET_REV 20 /* Get F/W revision */ -#define ATA_GET_MODEL 21 /* Get model name */ -#define ATA_GET_SN 22 /* Get serial number */ +#define ATA_GET_REV 20 /* Get F/W revision */ +#define ATA_GET_MODEL 21 /* Get model name */ +#define ATA_GET_SN 22 /* Get serial number */ /* NAND specific ioctl command */ -#define NAND_FORMAT 30 /* Create physical format */ +#define NAND_FORMAT 30 /* Create physical format */ #define _DISKIO diff --git a/src/bootldr/faulthandler.c b/src/bootldr/faulthandler.c index b2e2a5f..ed88a29 100644 --- a/src/bootldr/faulthandler.c +++ b/src/bootldr/faulthandler.c @@ -2,21 +2,26 @@ #include "config.h" #include "uart.h" -void HardFault_Handler(void) { - DBG_BL printf("HFSR: %lx\n", SCB->HFSR); - DBG_UART uart_putc('H'); - while (1) ; +void HardFault_Handler( void ) +{ + DBG_BL printf( "HFSR: %lx\n", SCB->HFSR ); + DBG_UART uart_putc( 'H' ); + + while ( 1 ) ; } -void MemManage_Handler(void) { - DBG_BL printf("MemManage - CFSR: %lx; MMFAR: %lx\n", SCB->CFSR, SCB->MMFAR); +void MemManage_Handler( void ) +{ + DBG_BL printf( "MemManage - CFSR: %lx; MMFAR: %lx\n", SCB->CFSR, SCB->MMFAR ); } -void BusFault_Handler(void) { - DBG_BL printf("BusFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR); +void BusFault_Handler( void ) +{ + DBG_BL printf( "BusFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR ); } -void UsageFault_Handler(void) { - DBG_BL printf("UsageFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR); +void UsageFault_Handler( void ) +{ + DBG_BL printf( "UsageFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR ); } diff --git a/src/bootldr/ff.c b/src/bootldr/ff.c index 9e454fc..79f0208 100644 --- a/src/bootldr/ff.c +++ b/src/bootldr/ff.c @@ -85,8 +85,8 @@ / Fixed f_mkfs() creates wrong FAT32 volume. /---------------------------------------------------------------------------*/ -#include "ff.h" /* FatFs configurations and declarations */ -#include "diskio.h" /* Declarations of low level disk I/O functions */ +#include "ff.h" /* FatFs configurations and declarations */ +#include "diskio.h" /* Declarations of low level disk I/O functions */ #include "config.h" #include "uart.h" @@ -106,9 +106,9 @@ #error Wrong sector size. #endif #if _MAX_SS != 512 -#define SS(fs) ((fs)->ssize) /* Multiple sector size */ +#define SS(fs) ((fs)->ssize) /* Multiple sector size */ #else -#define SS(fs) 512U /* Fixed sector size */ +#define SS(fs) 512U /* Fixed sector size */ #endif @@ -117,14 +117,14 @@ #if _USE_LFN == 1 #error Static LFN work area must not be used in re-entrant configuration. #endif -#define ENTER_FF(fs) { if (!lock_fs(fs)) return FR_TIMEOUT; } -#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } +#define ENTER_FF(fs) { if (!lock_fs(fs)) return FR_TIMEOUT; } +#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } #else -#define ENTER_FF(fs) -#define LEAVE_FF(fs, res) return res +#define ENTER_FF(fs) +#define LEAVE_FF(fs, res) return res #endif -#define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); } +#define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); } /* File shareing feature */ @@ -132,119 +132,120 @@ #if _FS_READONLY #error _FS_SHARE must be 0 on read-only cfg. #endif -typedef struct { - FATFS *fs; /* File ID 1, volume (NULL:blank entry) */ - DWORD clu; /* File ID 2, directory */ - WORD idx; /* File ID 3, directory index */ - WORD ctr; /* File open counter, 0:none, 0x01..0xFF:read open count, 0x100:write mode */ +typedef struct +{ + FATFS *fs; /* File ID 1, volume (NULL:blank entry) */ + DWORD clu; /* File ID 2, directory */ + WORD idx; /* File ID 3, directory index */ + WORD ctr; /* File open counter, 0:none, 0x01..0xFF:read open count, 0x100:write mode */ } FILESEM; #endif /* Misc definitions */ -#define LD_CLUST(dir) (((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO)) +#define LD_CLUST(dir) (((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO)) #define ST_CLUST(dir,cl) {ST_WORD(dir+DIR_FstClusLO, cl); ST_WORD(dir+DIR_FstClusHI, (DWORD)cl>>16);} /* Character code support macros */ -#define IsUpper(c) (((c)>='A')&&((c)<='Z')) -#define IsLower(c) (((c)>='a')&&((c)<='z')) -#define IsDigit(c) (((c)>='0')&&((c)<='9')) +#define IsUpper(c) (((c)>='A')&&((c)<='Z')) +#define IsLower(c) (((c)>='a')&&((c)<='z')) +#define IsDigit(c) (((c)>='0')&&((c)<='9')) -#if _DF1S /* Code page is DBCS */ +#if _DF1S /* Code page is DBCS */ -#ifdef _DF2S /* Two 1st byte areas */ -#define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E)) -#else /* One 1st byte area */ -#define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) +#ifdef _DF2S /* Two 1st byte areas */ +#define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E)) +#else /* One 1st byte area */ +#define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) #endif -#ifdef _DS3S /* Three 2nd byte areas */ -#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E)) -#else /* Two 2nd byte areas */ -#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E)) +#ifdef _DS3S /* Three 2nd byte areas */ +#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E)) +#else /* Two 2nd byte areas */ +#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E)) #endif -#else /* Code page is SBCS */ +#else /* Code page is SBCS */ -#define IsDBCS1(c) 0 -#define IsDBCS2(c) 0 +#define IsDBCS1(c) 0 +#define IsDBCS2(c) 0 #endif /* _DF1S */ /* Name status flags */ -#define NS 11 /* Offset of name status byte */ -#define NS_LOSS 0x01 /* Out of 8.3 format */ -#define NS_LFN 0x02 /* Force to create LFN entry */ -#define NS_LAST 0x04 /* Last segment */ -#define NS_BODY 0x08 /* Lower case flag (body) */ -#define NS_EXT 0x10 /* Lower case flag (ext) */ -#define NS_DOT 0x20 /* Dot entry */ +#define NS 11 /* Offset of name status byte */ +#define NS_LOSS 0x01 /* Out of 8.3 format */ +#define NS_LFN 0x02 /* Force to create LFN entry */ +#define NS_LAST 0x04 /* Last segment */ +#define NS_BODY 0x08 /* Lower case flag (body) */ +#define NS_EXT 0x10 /* Lower case flag (ext) */ +#define NS_DOT 0x20 /* Dot entry */ /* FAT sub-type boundaries */ /* Note that the FAT spec by Microsoft says 4085 but Windows works with 4087! */ -#define MIN_FAT16 4086 /* Minimum number of clusters for FAT16 */ -#define MIN_FAT32 65526 /* Minimum number of clusters for FAT32 */ +#define MIN_FAT16 4086 /* Minimum number of clusters for FAT16 */ +#define MIN_FAT32 65526 /* Minimum number of clusters for FAT32 */ /* FatFs refers the members in the FAT structures as byte array instead of / structure member because there are incompatibility of the packing option / between compilers. */ -#define BS_jmpBoot 0 -#define BS_OEMName 3 -#define BPB_BytsPerSec 11 -#define BPB_SecPerClus 13 -#define BPB_RsvdSecCnt 14 -#define BPB_NumFATs 16 -#define BPB_RootEntCnt 17 -#define BPB_TotSec16 19 -#define BPB_Media 21 -#define BPB_FATSz16 22 -#define BPB_SecPerTrk 24 -#define BPB_NumHeads 26 -#define BPB_HiddSec 28 -#define BPB_TotSec32 32 -#define BS_DrvNum 36 -#define BS_BootSig 38 -#define BS_VolID 39 -#define BS_VolLab 43 -#define BS_FilSysType 54 -#define BPB_FATSz32 36 -#define BPB_ExtFlags 40 -#define BPB_FSVer 42 -#define BPB_RootClus 44 -#define BPB_FSInfo 48 -#define BPB_BkBootSec 50 -#define BS_DrvNum32 64 -#define BS_BootSig32 66 -#define BS_VolID32 67 -#define BS_VolLab32 71 -#define BS_FilSysType32 82 -#define FSI_LeadSig 0 -#define FSI_StrucSig 484 -#define FSI_Free_Count 488 -#define FSI_Nxt_Free 492 -#define MBR_Table 446 -#define BS_55AA 510 +#define BS_jmpBoot 0 +#define BS_OEMName 3 +#define BPB_BytsPerSec 11 +#define BPB_SecPerClus 13 +#define BPB_RsvdSecCnt 14 +#define BPB_NumFATs 16 +#define BPB_RootEntCnt 17 +#define BPB_TotSec16 19 +#define BPB_Media 21 +#define BPB_FATSz16 22 +#define BPB_SecPerTrk 24 +#define BPB_NumHeads 26 +#define BPB_HiddSec 28 +#define BPB_TotSec32 32 +#define BS_DrvNum 36 +#define BS_BootSig 38 +#define BS_VolID 39 +#define BS_VolLab 43 +#define BS_FilSysType 54 +#define BPB_FATSz32 36 +#define BPB_ExtFlags 40 +#define BPB_FSVer 42 +#define BPB_RootClus 44 +#define BPB_FSInfo 48 +#define BPB_BkBootSec 50 +#define BS_DrvNum32 64 +#define BS_BootSig32 66 +#define BS_VolID32 67 +#define BS_VolLab32 71 +#define BS_FilSysType32 82 +#define FSI_LeadSig 0 +#define FSI_StrucSig 484 +#define FSI_Free_Count 488 +#define FSI_Nxt_Free 492 +#define MBR_Table 446 +#define BS_55AA 510 -#define DIR_Name 0 -#define DIR_Attr 11 -#define DIR_NTres 12 -#define DIR_CrtTime 14 -#define DIR_CrtDate 16 -#define DIR_FstClusHI 20 -#define DIR_WrtTime 22 -#define DIR_WrtDate 24 -#define DIR_FstClusLO 26 -#define DIR_FileSize 28 -#define LDIR_Ord 0 -#define LDIR_Attr 11 -#define LDIR_Type 12 -#define LDIR_Chksum 13 -#define LDIR_FstClusLO 26 +#define DIR_Name 0 +#define DIR_Attr 11 +#define DIR_NTres 12 +#define DIR_CrtTime 14 +#define DIR_CrtDate 16 +#define DIR_FstClusHI 20 +#define DIR_WrtTime 22 +#define DIR_WrtDate 24 +#define DIR_FstClusLO 26 +#define DIR_FileSize 28 +#define LDIR_Ord 0 +#define LDIR_Attr 11 +#define LDIR_Type 12 +#define LDIR_Chksum 13 +#define LDIR_FstClusLO 26 @@ -253,46 +254,46 @@ typedef struct { #if _VOLUMES static -FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */ +FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */ #else #error Number of drives must not be 0. #endif static -WORD Fsid; /* File system mount ID */ +WORD Fsid; /* File system mount ID */ #if _FS_RPATH static -BYTE CurrVol; /* Current drive */ +BYTE CurrVol; /* Current drive */ #endif #if _FS_SHARE static -FILESEM Files[_FS_SHARE]; /* File lock semaphores */ +FILESEM Files[_FS_SHARE]; /* File lock semaphores */ #endif -#if _USE_LFN == 0 /* No LFN */ -#define DEF_NAMEBUF BYTE sfn[12] -#define INIT_BUF(dobj) (dobj).fn = sfn -#define FREE_BUF() +#if _USE_LFN == 0 /* No LFN */ +#define DEF_NAMEBUF BYTE sfn[12] +#define INIT_BUF(dobj) (dobj).fn = sfn +#define FREE_BUF() -#elif _USE_LFN == 1 /* LFN with static LFN working buffer */ -static WCHAR LfnBuf[_MAX_LFN+1]; -#define DEF_NAMEBUF BYTE sfn[12] -#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; } -#define FREE_BUF() +#elif _USE_LFN == 1 /* LFN with static LFN working buffer */ +static WCHAR LfnBuf[_MAX_LFN + 1]; +#define DEF_NAMEBUF BYTE sfn[12] +#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; } +#define FREE_BUF() -#elif _USE_LFN == 2 /* LFN with dynamic LFN working buffer on the stack */ -#define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1] -#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; } -#define FREE_BUF() +#elif _USE_LFN == 2 /* LFN with dynamic LFN working buffer on the stack */ +#define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1] +#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; } +#define FREE_BUF() -#elif _USE_LFN == 3 /* LFN with dynamic LFN working buffer on the heap */ -#define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn -#define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \ - if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \ - (dobj).lfn = lfn; (dobj).fn = sfn; } -#define FREE_BUF() ff_memfree(lfn) +#elif _USE_LFN == 3 /* LFN with dynamic LFN working buffer on the heap */ +#define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn +#define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \ + if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \ + (dobj).lfn = lfn; (dobj).fn = sfn; } +#define FREE_BUF() ff_memfree(lfn) #else #error Wrong LFN configuration. @@ -314,45 +315,62 @@ static WCHAR LfnBuf[_MAX_LFN+1]; /* Copy memory to memory */ static -void mem_cpy (void* dst, const void* src, UINT cnt) { - BYTE *d = (BYTE*)dst; - const BYTE *s = (const BYTE*)src; +void mem_cpy ( void *dst, const void *src, UINT cnt ) +{ + BYTE *d = ( BYTE * )dst; + const BYTE *s = ( const BYTE * )src; #if _WORD_ACCESS == 1 - while (cnt >= sizeof(int)) { - *(int*)d = *(int*)s; - d += sizeof(int); s += sizeof(int); - cnt -= sizeof(int); - } + + while ( cnt >= sizeof( int ) ) + { + *( int * )d = *( int * )s; + d += sizeof( int ); s += sizeof( int ); + cnt -= sizeof( int ); + } + #endif - while (cnt--) - *d++ = *s++; + + while ( cnt-- ) + { + *d++ = *s++; + } } /* Fill memory */ static -void mem_set (void* dst, int val, UINT cnt) { - BYTE *d = (BYTE*)dst; +void mem_set ( void *dst, int val, UINT cnt ) +{ + BYTE *d = ( BYTE * )dst; - while (cnt--) - *d++ = (BYTE)val; + while ( cnt-- ) + { + *d++ = ( BYTE )val; + } } /* Compare memory to memory */ static -int mem_cmp (const void* dst, const void* src, UINT cnt) { - const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src; - int r = 0; +int mem_cmp ( const void *dst, const void *src, UINT cnt ) +{ + const BYTE *d = ( const BYTE * )dst, *s = ( const BYTE * )src; + int r = 0; - while (cnt-- && (r = *d++ - *s++) == 0) ; - return r; + while ( cnt-- && ( r = *d++ - *s++ ) == 0 ) ; + + return r; } /* Check if chr is contained in the string */ static -int chk_chr (const char* str, int chr) { - while (*str && *str != chr) str++; - return *str; +int chk_chr ( const char *str, int chr ) +{ + while ( *str && *str != chr ) + { + str++; + } + + return *str; } @@ -364,25 +382,26 @@ int chk_chr (const char* str, int chr) { static int lock_fs ( - FATFS *fs /* File system object */ + FATFS *fs /* File system object */ ) { - return ff_req_grant(fs->sobj); + return ff_req_grant( fs->sobj ); } static void unlock_fs ( - FATFS *fs, /* File system object */ - FRESULT res /* Result code to be returned */ + FATFS *fs, /* File system object */ + FRESULT res /* Result code to be returned */ ) { - if (res != FR_NOT_ENABLED && - res != FR_INVALID_DRIVE && - res != FR_INVALID_OBJECT && - res != FR_TIMEOUT) { - ff_rel_grant(fs->sobj); - } + if ( res != FR_NOT_ENABLED && + res != FR_INVALID_DRIVE && + res != FR_INVALID_OBJECT && + res != FR_TIMEOUT ) + { + ff_rel_grant( fs->sobj ); + } } #endif @@ -394,108 +413,154 @@ void unlock_fs ( #if _FS_SHARE static -FRESULT chk_lock ( /* Check if the file can be accessed */ - DIR* dj, /* Directory object pointing the file to be checked */ - int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ +FRESULT chk_lock ( /* Check if the file can be accessed */ + DIR *dj, /* Directory object pointing the file to be checked */ + int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ ) { - UINT i, be; + UINT i, be; - /* Search file semaphore table */ - for (i = be = 0; i < _FS_SHARE; i++) { - if (Files[i].fs) { /* Existing entry */ - if (Files[i].fs == dj->fs && /* Check if the file matched with an open file */ - Files[i].clu == dj->sclust && - Files[i].idx == dj->index) break; - } else { /* Blank entry */ - be++; - } - } - if (i == _FS_SHARE) /* The file is not opened */ - return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */ + /* Search file semaphore table */ + for ( i = be = 0; i < _FS_SHARE; i++ ) + { + if ( Files[i].fs ) /* Existing entry */ + { + if ( Files[i].fs == dj->fs && /* Check if the file matched with an open file */ + Files[i].clu == dj->sclust && + Files[i].idx == dj->index ) + { + break; + } + } + else /* Blank entry */ + { + be++; + } + } - /* The file has been opened. Reject any open against writing file and all write mode open */ - return (acc || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK; + if ( i == _FS_SHARE ) /* The file is not opened */ + { + return ( be || acc == 2 ) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */ + } + + /* The file has been opened. Reject any open against writing file and all write mode open */ + return ( acc || Files[i].ctr == 0x100 ) ? FR_LOCKED : FR_OK; } static -int enq_lock ( /* Check if an entry is available for a new file */ - FATFS* fs /* File system object */ +int enq_lock ( /* Check if an entry is available for a new file */ + FATFS *fs /* File system object */ ) { - UINT i; + UINT i; - for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ; - return (i == _FS_SHARE) ? 0 : 1; + for ( i = 0; i < _FS_SHARE && Files[i].fs; i++ ) ; + + return ( i == _FS_SHARE ) ? 0 : 1; } static -UINT inc_lock ( /* Increment file open counter and returns its index (0:int error) */ - DIR* dj, /* Directory object pointing the file to register or increment */ - int acc /* Desired access mode (0:Read, !0:Write) */ +UINT inc_lock ( /* Increment file open counter and returns its index (0:int error) */ + DIR *dj, /* Directory object pointing the file to register or increment */ + int acc /* Desired access mode (0:Read, !0:Write) */ ) { - UINT i; + UINT i; - for (i = 0; i < _FS_SHARE; i++) { /* Find the file */ - if (Files[i].fs == dj->fs && - Files[i].clu == dj->sclust && - Files[i].idx == dj->index) break; - } + for ( i = 0; i < _FS_SHARE; i++ ) /* Find the file */ + { + if ( Files[i].fs == dj->fs && + Files[i].clu == dj->sclust && + Files[i].idx == dj->index ) + { + break; + } + } - if (i == _FS_SHARE) { /* Not opened. Register it as new. */ - for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ; - if (i == _FS_SHARE) return 0; /* No space to register (int err) */ - Files[i].fs = dj->fs; - Files[i].clu = dj->sclust; - Files[i].idx = dj->index; - Files[i].ctr = 0; - } + if ( i == _FS_SHARE ) /* Not opened. Register it as new. */ + { + for ( i = 0; i < _FS_SHARE && Files[i].fs; i++ ) ; - if (acc && Files[i].ctr) return 0; /* Access violation (int err) */ + if ( i == _FS_SHARE ) + { + return 0; /* No space to register (int err) */ + } - Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ + Files[i].fs = dj->fs; + Files[i].clu = dj->sclust; + Files[i].idx = dj->index; + Files[i].ctr = 0; + } - return i + 1; + if ( acc && Files[i].ctr ) + { + return 0; /* Access violation (int err) */ + } + + Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ + + return i + 1; } static -FRESULT dec_lock ( /* Decrement file open counter */ - UINT i /* Semaphore index */ +FRESULT dec_lock ( /* Decrement file open counter */ + UINT i /* Semaphore index */ ) { - WORD n; - FRESULT res; + WORD n; + FRESULT res; - if (--i < _FS_SHARE) { - n = Files[i].ctr; - if (n == 0x100) n = 0; - if (n) n--; - Files[i].ctr = n; - if (!n) Files[i].fs = 0; - res = FR_OK; - } else { - res = FR_INT_ERR; - } - return res; + if ( --i < _FS_SHARE ) + { + n = Files[i].ctr; + + if ( n == 0x100 ) + { + n = 0; + } + + if ( n ) + { + n--; + } + + Files[i].ctr = n; + + if ( !n ) + { + Files[i].fs = 0; + } + + res = FR_OK; + } + else + { + res = FR_INT_ERR; + } + + return res; } static -void clear_lock ( /* Clear lock entries of the volume */ - FATFS *fs +void clear_lock ( /* Clear lock entries of the volume */ + FATFS *fs ) { - UINT i; + UINT i; - for (i = 0; i < _FS_SHARE; i++) { - if (Files[i].fs == fs) Files[i].fs = 0; - } + for ( i = 0; i < _FS_SHARE; i++ ) + { + if ( Files[i].fs == fs ) + { + Files[i].fs = 0; + } + } } #endif @@ -507,37 +572,54 @@ void clear_lock ( /* Clear lock entries of the volume */ static FRESULT move_window ( - FATFS *fs, /* File system object */ - DWORD sector /* Sector number to make appearance in the fs->win[] */ -) /* Move to zero only writes back dirty window */ + FATFS *fs, /* File system object */ + DWORD sector /* Sector number to make appearance in the fs->win[] */ +) /* Move to zero only writes back dirty window */ { - DWORD wsect; + DWORD wsect; - wsect = fs->winsect; - if (wsect != sector) { /* Changed current window */ + wsect = fs->winsect; + + if ( wsect != sector ) /* Changed current window */ + { #if !_FS_READONLY - if (fs->wflag) { /* Write back dirty window if needed */ - if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK) - return FR_DISK_ERR; - fs->wflag = 0; - if (wsect < (fs->fatbase + fs->fsize)) { /* In FAT area */ - BYTE nf; - for (nf = fs->n_fats; nf > 1; nf--) { /* Reflect the change to all FAT copies */ - wsect += fs->fsize; - disk_write(fs->drv, fs->win, wsect, 1); - } - } - } -#endif - if (sector) { - if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK) - return FR_DISK_ERR; - fs->winsect = sector; - } - } - return FR_OK; + if ( fs->wflag ) /* Write back dirty window if needed */ + { + if ( disk_write( fs->drv, fs->win, wsect, 1 ) != RES_OK ) + { + return FR_DISK_ERR; + } + + fs->wflag = 0; + + if ( wsect < ( fs->fatbase + fs->fsize ) ) /* In FAT area */ + { + BYTE nf; + + for ( nf = fs->n_fats; nf > 1; nf-- ) /* Reflect the change to all FAT copies */ + { + wsect += fs->fsize; + disk_write( fs->drv, fs->win, wsect, 1 ); + } + } + } + +#endif + + if ( sector ) + { + if ( disk_read( fs->drv, fs->win, sector, 1 ) != RES_OK ) + { + return FR_DISK_ERR; + } + + fs->winsect = sector; + } + } + + return FR_OK; } @@ -548,33 +630,39 @@ FRESULT move_window ( /*-----------------------------------------------------------------------*/ #if !_FS_READONLY static -FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */ - FATFS *fs /* File system object */ +FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */ + FATFS *fs /* File system object */ ) { - FRESULT res; + FRESULT res; - res = move_window(fs, 0); - if (res == FR_OK) { - /* Update FSInfo sector if needed */ - if (fs->fs_type == FS_FAT32 && fs->fsi_flag) { - fs->winsect = 0; - mem_set(fs->win, 0, 512); - ST_WORD(fs->win+BS_55AA, 0xAA55); - ST_DWORD(fs->win+FSI_LeadSig, 0x41615252); - ST_DWORD(fs->win+FSI_StrucSig, 0x61417272); - ST_DWORD(fs->win+FSI_Free_Count, fs->free_clust); - ST_DWORD(fs->win+FSI_Nxt_Free, fs->last_clust); - disk_write(fs->drv, fs->win, fs->fsi_sector, 1); - fs->fsi_flag = 0; - } - /* Make sure that no pending write process in the physical drive */ - if (disk_ioctl(fs->drv, CTRL_SYNC, (void*)0) != RES_OK) - res = FR_DISK_ERR; - } + res = move_window( fs, 0 ); - return res; + if ( res == FR_OK ) + { + /* Update FSInfo sector if needed */ + if ( fs->fs_type == FS_FAT32 && fs->fsi_flag ) + { + fs->winsect = 0; + mem_set( fs->win, 0, 512 ); + ST_WORD( fs->win + BS_55AA, 0xAA55 ); + ST_DWORD( fs->win + FSI_LeadSig, 0x41615252 ); + ST_DWORD( fs->win + FSI_StrucSig, 0x61417272 ); + ST_DWORD( fs->win + FSI_Free_Count, fs->free_clust ); + ST_DWORD( fs->win + FSI_Nxt_Free, fs->last_clust ); + disk_write( fs->drv, fs->win, fs->fsi_sector, 1 ); + fs->fsi_flag = 0; + } + + /* Make sure that no pending write process in the physical drive */ + if ( disk_ioctl( fs->drv, CTRL_SYNC, ( void * )0 ) != RES_OK ) + { + res = FR_DISK_ERR; + } + } + + return res; } #endif @@ -586,14 +674,19 @@ FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */ /*-----------------------------------------------------------------------*/ -DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ - FATFS *fs, /* File system object */ - DWORD clst /* Cluster# to be converted */ +DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to be converted */ ) { - clst -= 2; - if (clst >= (fs->n_fatent - 2)) return 0; /* Invalid cluster# */ - return clst * fs->csize + fs->database; + clst -= 2; + + if ( clst >= ( fs->n_fatent - 2 ) ) + { + return 0; /* Invalid cluster# */ + } + + return clst * fs->csize + fs->database; } @@ -604,39 +697,60 @@ DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ /*-----------------------------------------------------------------------*/ -DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */ - FATFS *fs, /* File system object */ - DWORD clst /* Cluster# to get the link information */ +DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to get the link information */ ) { - UINT wc, bc; - BYTE *p; + UINT wc, bc; + BYTE *p; - if (clst < 2 || clst >= fs->n_fatent) /* Chack range */ - return 1; + if ( clst < 2 || clst >= fs->n_fatent ) /* Chack range */ + { + return 1; + } - switch (fs->fs_type) { - case FS_FAT12 : - bc = (UINT)clst; bc += bc / 2; - if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; - wc = fs->win[bc % SS(fs)]; bc++; - if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; - wc |= fs->win[bc % SS(fs)] << 8; - return (clst & 1) ? (wc >> 4) : (wc & 0xFFF); + switch ( fs->fs_type ) + { + case FS_FAT12 : + bc = ( UINT )clst; bc += bc / 2; - case FS_FAT16 : - if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)))) break; - p = &fs->win[clst * 2 % SS(fs)]; - return LD_WORD(p); + if ( move_window( fs, fs->fatbase + ( bc / SS( fs ) ) ) ) + { + break; + } - case FS_FAT32 : - if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)))) break; - p = &fs->win[clst * 4 % SS(fs)]; - return LD_DWORD(p) & 0x0FFFFFFF; - } + wc = fs->win[bc % SS( fs )]; bc++; - return 0xFFFFFFFF; /* An error occurred at the disk I/O layer */ + if ( move_window( fs, fs->fatbase + ( bc / SS( fs ) ) ) ) + { + break; + } + + wc |= fs->win[bc % SS( fs )] << 8; + return ( clst & 1 ) ? ( wc >> 4 ) : ( wc & 0xFFF ); + + case FS_FAT16 : + if ( move_window( fs, fs->fatbase + ( clst / ( SS( fs ) / 2 ) ) ) ) + { + break; + } + + p = &fs->win[clst * 2 % SS( fs )]; + return LD_WORD( p ); + + case FS_FAT32 : + if ( move_window( fs, fs->fatbase + ( clst / ( SS( fs ) / 4 ) ) ) ) + { + break; + } + + p = &fs->win[clst * 4 % SS( fs )]; + return LD_DWORD( p ) & 0x0FFFFFFF; + } + + return 0xFFFFFFFF; /* An error occurred at the disk I/O layer */ } @@ -648,57 +762,82 @@ DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status #if !_FS_READONLY FRESULT put_fat ( - FATFS *fs, /* File system object */ - DWORD clst, /* Cluster# to be changed in range of 2 to fs->n_fatent - 1 */ - DWORD val /* New value to mark the cluster */ + FATFS *fs, /* File system object */ + DWORD clst, /* Cluster# to be changed in range of 2 to fs->n_fatent - 1 */ + DWORD val /* New value to mark the cluster */ ) { - UINT bc; - BYTE *p; - FRESULT res; + UINT bc; + BYTE *p; + FRESULT res; - if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ - res = FR_INT_ERR; + if ( clst < 2 || clst >= fs->n_fatent ) /* Check range */ + { + res = FR_INT_ERR; - } else { - switch (fs->fs_type) { - case FS_FAT12 : - bc = clst; bc += bc / 2; - res = move_window(fs, fs->fatbase + (bc / SS(fs))); - if (res != FR_OK) break; - p = &fs->win[bc % SS(fs)]; - *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; - bc++; - fs->wflag = 1; - res = move_window(fs, fs->fatbase + (bc / SS(fs))); - if (res != FR_OK) break; - p = &fs->win[bc % SS(fs)]; - *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); - break; + } + else + { + switch ( fs->fs_type ) + { + case FS_FAT12 : + bc = clst; bc += bc / 2; + res = move_window( fs, fs->fatbase + ( bc / SS( fs ) ) ); - case FS_FAT16 : - res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); - if (res != FR_OK) break; - p = &fs->win[clst * 2 % SS(fs)]; - ST_WORD(p, (WORD)val); - break; + if ( res != FR_OK ) + { + break; + } - case FS_FAT32 : - res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); - if (res != FR_OK) break; - p = &fs->win[clst * 4 % SS(fs)]; - val |= LD_DWORD(p) & 0xF0000000; - ST_DWORD(p, val); - break; + p = &fs->win[bc % SS( fs )]; + *p = ( clst & 1 ) ? ( ( *p & 0x0F ) | ( ( BYTE )val << 4 ) ) : ( BYTE )val; + bc++; + fs->wflag = 1; + res = move_window( fs, fs->fatbase + ( bc / SS( fs ) ) ); - default : - res = FR_INT_ERR; - } - fs->wflag = 1; - } + if ( res != FR_OK ) + { + break; + } - return res; + p = &fs->win[bc % SS( fs )]; + *p = ( clst & 1 ) ? ( BYTE )( val >> 4 ) : ( ( *p & 0xF0 ) | ( ( BYTE )( val >> 8 ) & 0x0F ) ); + break; + + case FS_FAT16 : + res = move_window( fs, fs->fatbase + ( clst / ( SS( fs ) / 2 ) ) ); + + if ( res != FR_OK ) + { + break; + } + + p = &fs->win[clst * 2 % SS( fs )]; + ST_WORD( p, ( WORD )val ); + break; + + case FS_FAT32 : + res = move_window( fs, fs->fatbase + ( clst / ( SS( fs ) / 4 ) ) ); + + if ( res != FR_OK ) + { + break; + } + + p = &fs->win[clst * 4 % SS( fs )]; + val |= LD_DWORD( p ) & 0xF0000000; + ST_DWORD( p, val ); + break; + + default : + res = FR_INT_ERR; + } + + fs->wflag = 1; + } + + return res; } #endif /* !_FS_READONLY */ @@ -711,47 +850,79 @@ FRESULT put_fat ( #if !_FS_READONLY static FRESULT remove_chain ( - FATFS *fs, /* File system object */ - DWORD clst /* Cluster# to remove a chain from */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to remove a chain from */ ) { - FRESULT res; - DWORD nxt; + FRESULT res; + DWORD nxt; #if _USE_ERASE - DWORD scl = clst, ecl = clst, resion[2]; + DWORD scl = clst, ecl = clst, resion[2]; #endif - if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ - res = FR_INT_ERR; + if ( clst < 2 || clst >= fs->n_fatent ) /* Check range */ + { + res = FR_INT_ERR; + + } + else + { + res = FR_OK; + + while ( clst < fs->n_fatent ) /* Not a last link? */ + { + nxt = get_fat( fs, clst ); /* Get cluster status */ + + if ( nxt == 0 ) + { + break; /* Empty cluster? */ + } + + if ( nxt == 1 ) + { + res = FR_INT_ERR; /* Internal error? */ + break; + } + + if ( nxt == 0xFFFFFFFF ) + { + res = FR_DISK_ERR; /* Disk error? */ + break; + } + + res = put_fat( fs, clst, 0 ); /* Mark the cluster "empty" */ + + if ( res != FR_OK ) + { + break; + } + + if ( fs->free_clust != 0xFFFFFFFF ) /* Update FSInfo */ + { + fs->free_clust++; + fs->fsi_flag = 1; + } - } else { - res = FR_OK; - while (clst < fs->n_fatent) { /* Not a last link? */ - nxt = get_fat(fs, clst); /* Get cluster status */ - if (nxt == 0) break; /* Empty cluster? */ - if (nxt == 1) { res = FR_INT_ERR; break; } /* Internal error? */ - if (nxt == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } /* Disk error? */ - res = put_fat(fs, clst, 0); /* Mark the cluster "empty" */ - if (res != FR_OK) break; - if (fs->free_clust != 0xFFFFFFFF) { /* Update FSInfo */ - fs->free_clust++; - fs->fsi_flag = 1; - } #if _USE_ERASE - if (ecl + 1 == nxt) { /* Next cluster is contiguous */ - ecl = nxt; - } else { /* End of contiguous clusters */ - resion[0] = clust2sect(fs, scl); /* Start sector */ - resion[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */ - disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, resion); /* Erase the block */ - scl = ecl = nxt; - } -#endif - clst = nxt; /* Next cluster */ - } - } - return res; + if ( ecl + 1 == nxt ) /* Next cluster is contiguous */ + { + ecl = nxt; + } + else /* End of contiguous clusters */ + { + resion[0] = clust2sect( fs, scl ); /* Start sector */ + resion[1] = clust2sect( fs, ecl ) + fs->csize - 1; /* End sector */ + disk_ioctl( fs->drv, CTRL_ERASE_SECTOR, resion ); /* Erase the block */ + scl = ecl = nxt; + } + +#endif + clst = nxt; /* Next cluster */ + } + } + + return res; } #endif @@ -763,55 +934,98 @@ FRESULT remove_chain ( /*-----------------------------------------------------------------------*/ #if !_FS_READONLY static -DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ - FATFS *fs, /* File system object */ - DWORD clst /* Cluster# to stretch. 0 means create a new chain. */ +DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to stretch. 0 means create a new chain. */ ) { - DWORD cs, ncl, scl; - FRESULT res; + DWORD cs, ncl, scl; + FRESULT res; - if (clst == 0) { /* Create a new chain */ - scl = fs->last_clust; /* Get suggested start point */ - if (!scl || scl >= fs->n_fatent) scl = 1; - } - else { /* Stretch the current chain */ - cs = get_fat(fs, clst); /* Check the cluster status */ - if (cs < 2) return 1; /* It is an invalid cluster */ - if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */ - scl = clst; - } + if ( clst == 0 ) /* Create a new chain */ + { + scl = fs->last_clust; /* Get suggested start point */ - ncl = scl; /* Start cluster */ - for (;;) { - ncl++; /* Next cluster */ - if (ncl >= fs->n_fatent) { /* Wrap around */ - ncl = 2; - if (ncl > scl) return 0; /* No free cluster */ - } - cs = get_fat(fs, ncl); /* Get the cluster status */ - if (cs == 0) break; /* Found a free cluster */ - if (cs == 0xFFFFFFFF || cs == 1)/* An error occurred */ - return cs; - if (ncl == scl) return 0; /* No free cluster */ - } + if ( !scl || scl >= fs->n_fatent ) + { + scl = 1; + } + } + else /* Stretch the current chain */ + { + cs = get_fat( fs, clst ); /* Check the cluster status */ - res = put_fat(fs, ncl, 0x0FFFFFFF); /* Mark the new cluster "last link" */ - if (res == FR_OK && clst != 0) { - res = put_fat(fs, clst, ncl); /* Link it to the previous one if needed */ - } - if (res == FR_OK) { - fs->last_clust = ncl; /* Update FSINFO */ - if (fs->free_clust != 0xFFFFFFFF) { - fs->free_clust--; - fs->fsi_flag = 1; - } - } else { - ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1; - } + if ( cs < 2 ) + { + return 1; /* It is an invalid cluster */ + } - return ncl; /* Return new cluster number or error code */ + if ( cs < fs->n_fatent ) + { + return cs; /* It is already followed by next cluster */ + } + + scl = clst; + } + + ncl = scl; /* Start cluster */ + + for ( ;; ) + { + ncl++; /* Next cluster */ + + if ( ncl >= fs->n_fatent ) /* Wrap around */ + { + ncl = 2; + + if ( ncl > scl ) + { + return 0; /* No free cluster */ + } + } + + cs = get_fat( fs, ncl ); /* Get the cluster status */ + + if ( cs == 0 ) + { + break; /* Found a free cluster */ + } + + if ( cs == 0xFFFFFFFF || cs == 1 ) /* An error occurred */ + { + return cs; + } + + if ( ncl == scl ) + { + return 0; /* No free cluster */ + } + } + + res = put_fat( fs, ncl, 0x0FFFFFFF ); /* Mark the new cluster "last link" */ + + if ( res == FR_OK && clst != 0 ) + { + res = put_fat( fs, clst, ncl ); /* Link it to the previous one if needed */ + } + + if ( res == FR_OK ) + { + fs->last_clust = ncl; /* Update FSINFO */ + + if ( fs->free_clust != 0xFFFFFFFF ) + { + fs->free_clust--; + fs->fsi_flag = 1; + } + } + else + { + ncl = ( res == FR_DISK_ERR ) ? 0xFFFFFFFF : 1; + } + + return ncl; /* Return new cluster number or error code */ } #endif /* !_FS_READONLY */ @@ -824,43 +1038,66 @@ DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk err static FRESULT dir_sdi ( - DIR *dj, /* Pointer to directory object */ - WORD idx /* Directory index number */ + DIR *dj, /* Pointer to directory object */ + WORD idx /* Directory index number */ ) { - DWORD clst; - WORD ic; + DWORD clst; + WORD ic; - dj->index = idx; - clst = dj->sclust; - if (clst == 1 || clst >= dj->fs->n_fatent) /* Check start cluster range */ - return FR_INT_ERR; - if (!clst && dj->fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */ - clst = dj->fs->dirbase; + dj->index = idx; + clst = dj->sclust; - if (clst == 0) { /* Static table (root-dir in FAT12/16) */ - dj->clust = clst; - if (idx >= dj->fs->n_rootdir) /* Index is out of range */ - return FR_INT_ERR; - dj->sect = dj->fs->dirbase + idx / (SS(dj->fs) / 32); /* Sector# */ - } - else { /* Dynamic table (sub-dirs or root-dir in FAT32) */ - ic = SS(dj->fs) / 32 * dj->fs->csize; /* Entries per cluster */ - while (idx >= ic) { /* Follow cluster chain */ - clst = get_fat(dj->fs, clst); /* Get next cluster */ - if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ - if (clst < 2 || clst >= dj->fs->n_fatent) /* Reached to end of table or int error */ - return FR_INT_ERR; - idx -= ic; - } - dj->clust = clst; - dj->sect = clust2sect(dj->fs, clst) + idx / (SS(dj->fs) / 32); /* Sector# */ - } + if ( clst == 1 || clst >= dj->fs->n_fatent ) /* Check start cluster range */ + { + return FR_INT_ERR; + } - dj->dir = dj->fs->win + (idx % (SS(dj->fs) / 32)) * 32; /* Ptr to the entry in the sector */ + if ( !clst && dj->fs->fs_type == FS_FAT32 ) /* Replace cluster# 0 with root cluster# if in FAT32 */ + { + clst = dj->fs->dirbase; + } - return FR_OK; /* Seek succeeded */ + if ( clst == 0 ) /* Static table (root-dir in FAT12/16) */ + { + dj->clust = clst; + + if ( idx >= dj->fs->n_rootdir ) /* Index is out of range */ + { + return FR_INT_ERR; + } + + dj->sect = dj->fs->dirbase + idx / ( SS( dj->fs ) / 32 ); /* Sector# */ + } + else /* Dynamic table (sub-dirs or root-dir in FAT32) */ + { + ic = SS( dj->fs ) / 32 * dj->fs->csize; /* Entries per cluster */ + + while ( idx >= ic ) /* Follow cluster chain */ + { + clst = get_fat( dj->fs, clst ); /* Get next cluster */ + + if ( clst == 0xFFFFFFFF ) + { + return FR_DISK_ERR; /* Disk error */ + } + + if ( clst < 2 || clst >= dj->fs->n_fatent ) /* Reached to end of table or int error */ + { + return FR_INT_ERR; + } + + idx -= ic; + } + + dj->clust = clst; + dj->sect = clust2sect( dj->fs, clst ) + idx / ( SS( dj->fs ) / 32 ); /* Sector# */ + } + + dj->dir = dj->fs->win + ( idx % ( SS( dj->fs ) / 32 ) ) * 32; /* Ptr to the entry in the sector */ + + return FR_OK; /* Seek succeeded */ } @@ -871,63 +1108,113 @@ FRESULT dir_sdi ( /*-----------------------------------------------------------------------*/ static -FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT and could not stretch */ - DIR *dj, /* Pointer to directory object */ - int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ +FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT and could not stretch */ + DIR *dj, /* Pointer to directory object */ + int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ ) { - DWORD clst; - WORD i; + DWORD clst; + WORD i; - i = dj->index + 1; - if (!i || !dj->sect) /* Report EOT when index has reached 65535 */ - return FR_NO_FILE; + i = dj->index + 1; - if (!(i % (SS(dj->fs) / 32))) { /* Sector changed? */ - dj->sect++; /* Next sector */ + if ( !i || !dj->sect ) /* Report EOT when index has reached 65535 */ + { + return FR_NO_FILE; + } - if (dj->clust == 0) { /* Static table */ - if (i >= dj->fs->n_rootdir) /* Report EOT when end of table */ - return FR_NO_FILE; - } - else { /* Dynamic table */ - if (((i / (SS(dj->fs) / 32)) & (dj->fs->csize - 1)) == 0) { /* Cluster changed? */ - clst = get_fat(dj->fs, dj->clust); /* Get next cluster */ - if (clst <= 1) return FR_INT_ERR; - if (clst == 0xFFFFFFFF) return FR_DISK_ERR; - if (clst >= dj->fs->n_fatent) { /* When it reached end of dynamic table */ + if ( !( i % ( SS( dj->fs ) / 32 ) ) ) /* Sector changed? */ + { + dj->sect++; /* Next sector */ + + if ( dj->clust == 0 ) /* Static table */ + { + if ( i >= dj->fs->n_rootdir ) /* Report EOT when end of table */ + { + return FR_NO_FILE; + } + } + else /* Dynamic table */ + { + if ( ( ( i / ( SS( dj->fs ) / 32 ) ) & ( dj->fs->csize - 1 ) ) == 0 ) /* Cluster changed? */ + { + clst = get_fat( dj->fs, dj->clust ); /* Get next cluster */ + + if ( clst <= 1 ) + { + return FR_INT_ERR; + } + + if ( clst == 0xFFFFFFFF ) + { + return FR_DISK_ERR; + } + + if ( clst >= dj->fs->n_fatent ) /* When it reached end of dynamic table */ + { #if !_FS_READONLY - BYTE c; - if (!stretch) return FR_NO_FILE; /* When do not stretch, report EOT */ - clst = create_chain(dj->fs, dj->clust); /* Stretch cluster chain */ - if (clst == 0) return FR_DENIED; /* No free cluster */ - if (clst == 1) return FR_INT_ERR; - if (clst == 0xFFFFFFFF) return FR_DISK_ERR; - /* Clean-up stretched table */ - if (move_window(dj->fs, 0)) return FR_DISK_ERR; /* Flush active window */ - mem_set(dj->fs->win, 0, SS(dj->fs)); /* Clear window buffer */ - dj->fs->winsect = clust2sect(dj->fs, clst); /* Cluster start sector */ - for (c = 0; c < dj->fs->csize; c++) { /* Fill the new cluster with 0 */ - dj->fs->wflag = 1; - if (move_window(dj->fs, 0)) return FR_DISK_ERR; - dj->fs->winsect++; - } - dj->fs->winsect -= c; /* Rewind window address */ + BYTE c; + + if ( !stretch ) + { + return FR_NO_FILE; /* When do not stretch, report EOT */ + } + + clst = create_chain( dj->fs, dj->clust ); /* Stretch cluster chain */ + + if ( clst == 0 ) + { + return FR_DENIED; /* No free cluster */ + } + + if ( clst == 1 ) + { + return FR_INT_ERR; + } + + if ( clst == 0xFFFFFFFF ) + { + return FR_DISK_ERR; + } + + /* Clean-up stretched table */ + if ( move_window( dj->fs, 0 ) ) + { + return FR_DISK_ERR; /* Flush active window */ + } + + mem_set( dj->fs->win, 0, SS( dj->fs ) ); /* Clear window buffer */ + dj->fs->winsect = clust2sect( dj->fs, clst ); /* Cluster start sector */ + + for ( c = 0; c < dj->fs->csize; c++ ) /* Fill the new cluster with 0 */ + { + dj->fs->wflag = 1; + + if ( move_window( dj->fs, 0 ) ) + { + return FR_DISK_ERR; + } + + dj->fs->winsect++; + } + + dj->fs->winsect -= c; /* Rewind window address */ #else - return FR_NO_FILE; /* Report EOT */ + return FR_NO_FILE; /* Report EOT */ #endif - } - dj->clust = clst; /* Initialize data for new cluster */ - dj->sect = clust2sect(dj->fs, clst); - } - } - } + } - dj->index = i; - dj->dir = dj->fs->win + (i % (SS(dj->fs) / 32)) * 32; + dj->clust = clst; /* Initialize data for new cluster */ + dj->sect = clust2sect( dj->fs, clst ); + } + } + } - return FR_OK; + dj->index = i; + dj->dir = dj->fs->win + ( i % ( SS( dj->fs ) / 32 ) ) * 32; + + return FR_OK; } @@ -938,99 +1225,149 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an /*-----------------------------------------------------------------------*/ #if _USE_LFN static -const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* Offset of LFN chars in the directory entry */ +const BYTE LfnOfs[] = {1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30}; /* Offset of LFN chars in the directory entry */ static -int cmp_lfn ( /* 1:Matched, 0:Not matched */ - WCHAR *lfnbuf, /* Pointer to the LFN to be compared */ - BYTE *dir /* Pointer to the directory entry containing a part of LFN */ +int cmp_lfn ( /* 1:Matched, 0:Not matched */ + WCHAR *lfnbuf, /* Pointer to the LFN to be compared */ + BYTE *dir /* Pointer to the directory entry containing a part of LFN */ ) { - UINT i, s; - WCHAR wc, uc; + UINT i, s; + WCHAR wc, uc; - i = ((dir[LDIR_Ord] & 0xBF) - 1) * 13; /* Get offset in the LFN buffer */ - s = 0; wc = 1; - do { - uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */ - if (wc) { /* Last char has not been processed */ - wc = ff_wtoupper(uc); /* Convert it to upper case */ - if (i >= _MAX_LFN || wc != ff_wtoupper(lfnbuf[i++])) /* Compare it */ - return 0; /* Not matched */ - } else { - if (uc != 0xFFFF) return 0; /* Check filler */ - } - } while (++s < 13); /* Repeat until all chars in the entry are checked */ + i = ( ( dir[LDIR_Ord] & 0xBF ) - 1 ) * 13; /* Get offset in the LFN buffer */ + s = 0; wc = 1; - if ((dir[LDIR_Ord] & 0x40) && wc && lfnbuf[i]) /* Last segment matched but different length */ - return 0; + do + { + uc = LD_WORD( dir + LfnOfs[s] ); /* Pick an LFN character from the entry */ - return 1; /* The part of LFN matched */ + if ( wc ) /* Last char has not been processed */ + { + wc = ff_wtoupper( uc ); /* Convert it to upper case */ + + if ( i >= _MAX_LFN || wc != ff_wtoupper( lfnbuf[i++] ) ) /* Compare it */ + { + return 0; /* Not matched */ + } + } + else + { + if ( uc != 0xFFFF ) + { + return 0; /* Check filler */ + } + } + } + while ( ++s < 13 ); /* Repeat until all chars in the entry are checked */ + + if ( ( dir[LDIR_Ord] & 0x40 ) && wc && lfnbuf[i] ) /* Last segment matched but different length */ + { + return 0; + } + + return 1; /* The part of LFN matched */ } static -int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */ - WCHAR *lfnbuf, /* Pointer to the Unicode-LFN buffer */ - BYTE *dir /* Pointer to the directory entry */ +int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */ + WCHAR *lfnbuf, /* Pointer to the Unicode-LFN buffer */ + BYTE *dir /* Pointer to the directory entry */ ) { - UINT i, s; - WCHAR wc, uc; + UINT i, s; + WCHAR wc, uc; - i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */ + i = ( ( dir[LDIR_Ord] & 0x3F ) - 1 ) * 13; /* Offset in the LFN buffer */ - s = 0; wc = 1; - do { - uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */ - if (wc) { /* Last char has not been processed */ - if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ - lfnbuf[i++] = wc = uc; /* Store it */ - } else { - if (uc != 0xFFFF) return 0; /* Check filler */ - } - } while (++s < 13); /* Read all character in the entry */ + s = 0; wc = 1; - if (dir[LDIR_Ord] & 0x40) { /* Put terminator if it is the last LFN part */ - if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ - lfnbuf[i] = 0; - } + do + { + uc = LD_WORD( dir + LfnOfs[s] ); /* Pick an LFN character from the entry */ - return 1; + if ( wc ) /* Last char has not been processed */ + { + if ( i >= _MAX_LFN ) + { + return 0; /* Buffer overflow? */ + } + + lfnbuf[i++] = wc = uc; /* Store it */ + } + else + { + if ( uc != 0xFFFF ) + { + return 0; /* Check filler */ + } + } + } + while ( ++s < 13 ); /* Read all character in the entry */ + + if ( dir[LDIR_Ord] & 0x40 ) /* Put terminator if it is the last LFN part */ + { + if ( i >= _MAX_LFN ) + { + return 0; /* Buffer overflow? */ + } + + lfnbuf[i] = 0; + } + + return 1; } #if !_FS_READONLY static void fit_lfn ( - const WCHAR *lfnbuf, /* Pointer to the LFN buffer */ - BYTE *dir, /* Pointer to the directory entry */ - BYTE ord, /* LFN order (1-20) */ - BYTE sum /* SFN sum */ + const WCHAR *lfnbuf, /* Pointer to the LFN buffer */ + BYTE *dir, /* Pointer to the directory entry */ + BYTE ord, /* LFN order (1-20) */ + BYTE sum /* SFN sum */ ) { - UINT i, s; - WCHAR wc; + UINT i, s; + WCHAR wc; - dir[LDIR_Chksum] = sum; /* Set check sum */ - dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */ - dir[LDIR_Type] = 0; - ST_WORD(dir+LDIR_FstClusLO, 0); + dir[LDIR_Chksum] = sum; /* Set check sum */ + dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */ + dir[LDIR_Type] = 0; + ST_WORD( dir + LDIR_FstClusLO, 0 ); - i = (ord - 1) * 13; /* Get offset in the LFN buffer */ - s = wc = 0; - do { - if (wc != 0xFFFF) wc = lfnbuf[i++]; /* Get an effective char */ - ST_WORD(dir+LfnOfs[s], wc); /* Put it */ - if (!wc) wc = 0xFFFF; /* Padding chars following last char */ - } while (++s < 13); - if (wc == 0xFFFF || !lfnbuf[i]) ord |= 0x40; /* Bottom LFN part is the start of LFN sequence */ - dir[LDIR_Ord] = ord; /* Set the LFN order */ + i = ( ord - 1 ) * 13; /* Get offset in the LFN buffer */ + s = wc = 0; + + do + { + if ( wc != 0xFFFF ) + { + wc = lfnbuf[i++]; /* Get an effective char */ + } + + ST_WORD( dir + LfnOfs[s], wc ); /* Put it */ + + if ( !wc ) + { + wc = 0xFFFF; /* Padding chars following last char */ + } + } + while ( ++s < 13 ); + + if ( wc == 0xFFFF || !lfnbuf[i] ) + { + ord |= 0x40; /* Bottom LFN part is the start of LFN sequence */ + } + + dir[LDIR_Ord] = ord; /* Set the LFN order */ } #endif @@ -1043,42 +1380,65 @@ void fit_lfn ( /*-----------------------------------------------------------------------*/ #if _USE_LFN void gen_numname ( - BYTE *dst, /* Pointer to generated SFN */ - const BYTE *src, /* Pointer to source SFN to be modified */ - const WCHAR *lfn, /* Pointer to LFN */ - WORD seq /* Sequence number */ + BYTE *dst, /* Pointer to generated SFN */ + const BYTE *src, /* Pointer to source SFN to be modified */ + const WCHAR *lfn, /* Pointer to LFN */ + WORD seq /* Sequence number */ ) { - BYTE ns[8], c; - UINT i, j; + BYTE ns[8], c; + UINT i, j; - mem_cpy(dst, src, 11); + mem_cpy( dst, src, 11 ); - if (seq > 5) { /* On many collisions, generate a hash number instead of sequential number */ - do seq = (seq >> 1) + (seq << 15) + (WORD)*lfn++; while (*lfn); - } + if ( seq > 5 ) /* On many collisions, generate a hash number instead of sequential number */ + { + do + { + seq = ( seq >> 1 ) + ( seq << 15 ) + ( WORD ) * lfn++; + } + while ( *lfn ); + } - /* itoa */ - i = 7; - do { - c = (seq % 16) + '0'; - if (c > '9') c += 7; - ns[i--] = c; - seq /= 16; - } while (seq); - ns[i] = '~'; + /* itoa */ + i = 7; - /* Append the number */ - for (j = 0; j < i && dst[j] != ' '; j++) { - if (IsDBCS1(dst[j])) { - if (j == i - 1) break; - j++; - } - } - do { - dst[j++] = (i < 8) ? ns[i++] : ' '; - } while (j < 8); + do + { + c = ( seq % 16 ) + '0'; + + if ( c > '9' ) + { + c += 7; + } + + ns[i--] = c; + seq /= 16; + } + while ( seq ); + + ns[i] = '~'; + + /* Append the number */ + for ( j = 0; j < i && dst[j] != ' '; j++ ) + { + if ( IsDBCS1( dst[j] ) ) + { + if ( j == i - 1 ) + { + break; + } + + j++; + } + } + + do + { + dst[j++] = ( i < 8 ) ? ns[i++] : ' '; + } + while ( j < 8 ); } #endif @@ -1091,14 +1451,19 @@ void gen_numname ( #if _USE_LFN static BYTE sum_sfn ( - const BYTE *dir /* Ptr to directory entry */ + const BYTE *dir /* Ptr to directory entry */ ) { - BYTE sum = 0; - UINT n = 11; + BYTE sum = 0; + UINT n = 11; - do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n); - return sum; + do + { + sum = ( sum >> 1 ) + ( sum << 7 ) + *dir++; + } + while ( --n ); + + return sum; } #endif @@ -1111,56 +1476,97 @@ BYTE sum_sfn ( static FRESULT dir_find ( - DIR *dj /* Pointer to the directory object linked to the file name */ + DIR *dj /* Pointer to the directory object linked to the file name */ ) { - FRESULT res; - BYTE c, *dir; + FRESULT res; + BYTE c, *dir; #if _USE_LFN - BYTE a, ord, sum; + BYTE a, ord, sum; #endif - res = dir_sdi(dj, 0); /* Rewind directory object */ - if (res != FR_OK) return res; + res = dir_sdi( dj, 0 ); /* Rewind directory object */ + + if ( res != FR_OK ) + { + return res; + } #if _USE_LFN - ord = sum = 0xFF; + ord = sum = 0xFF; #endif - do { - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - dir = dj->dir; /* Ptr to the directory entry of current index */ - c = dir[DIR_Name]; - if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ -#if _USE_LFN /* LFN configuration */ - a = dir[DIR_Attr] & AM_MASK; - if (c == 0xE5 || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ - ord = 0xFF; - } else { - if (a == AM_LFN) { /* An LFN entry is found */ - if (dj->lfn) { - if (c & 0x40) { /* Is it start of LFN sequence? */ - sum = dir[LDIR_Chksum]; - c &= 0xBF; ord = c; /* LFN start order */ - dj->lfn_idx = dj->index; - } - /* Check validity of the LFN entry and compare it with given name */ - ord = (c == ord && sum == dir[LDIR_Chksum] && cmp_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF; - } - } else { /* An SFN entry is found */ - if (!ord && sum == sum_sfn(dir)) break; /* LFN matched? */ - ord = 0xFF; dj->lfn_idx = 0xFFFF; /* Reset LFN sequence */ - if (!(dj->fn[NS] & NS_LOSS) && !mem_cmp(dir, dj->fn, 11)) break; /* SFN matched? */ - } - } -#else /* Non LFN configuration */ - if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */ - break; -#endif - res = dir_next(dj, 0); /* Next entry */ - } while (res == FR_OK); - return res; + do + { + res = move_window( dj->fs, dj->sect ); + + if ( res != FR_OK ) + { + break; + } + + dir = dj->dir; /* Ptr to the directory entry of current index */ + c = dir[DIR_Name]; + + if ( c == 0 ) + { + res = FR_NO_FILE; /* Reached to end of table */ + break; + } + +#if _USE_LFN /* LFN configuration */ + a = dir[DIR_Attr] & AM_MASK; + + if ( c == 0xE5 || ( ( a & AM_VOL ) && a != AM_LFN ) ) /* An entry without valid data */ + { + ord = 0xFF; + } + else + { + if ( a == AM_LFN ) /* An LFN entry is found */ + { + if ( dj->lfn ) + { + if ( c & 0x40 ) /* Is it start of LFN sequence? */ + { + sum = dir[LDIR_Chksum]; + c &= 0xBF; ord = c; /* LFN start order */ + dj->lfn_idx = dj->index; + } + + /* Check validity of the LFN entry and compare it with given name */ + ord = ( c == ord && sum == dir[LDIR_Chksum] && cmp_lfn( dj->lfn, dir ) ) ? ord - 1 : 0xFF; + } + } + else /* An SFN entry is found */ + { + if ( !ord && sum == sum_sfn( dir ) ) + { + break; /* LFN matched? */ + } + + ord = 0xFF; dj->lfn_idx = 0xFFFF; /* Reset LFN sequence */ + + if ( !( dj->fn[NS] & NS_LOSS ) && !mem_cmp( dir, dj->fn, 11 ) ) + { + break; /* SFN matched? */ + } + } + } + +#else /* Non LFN configuration */ + + if ( !( dir[DIR_Attr] & AM_VOL ) && !mem_cmp( dir, dj->fn, 11 ) ) /* Is it a valid entry? */ + { + break; + } + +#endif + res = dir_next( dj, 0 ); /* Next entry */ + } + while ( res == FR_OK ); + + return res; } @@ -1172,52 +1578,89 @@ FRESULT dir_find ( #if _FS_MINIMIZE <= 1 static FRESULT dir_read ( - DIR *dj /* Pointer to the directory object that pointing the entry to be read */ + DIR *dj /* Pointer to the directory object that pointing the entry to be read */ ) { - FRESULT res; - BYTE c, *dir; + FRESULT res; + BYTE c, *dir; #if _USE_LFN - BYTE a, ord = 0xFF, sum = 0xFF; + BYTE a, ord = 0xFF, sum = 0xFF; #endif - res = FR_NO_FILE; - while (dj->sect) { - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - dir = dj->dir; /* Ptr to the directory entry of current index */ - c = dir[DIR_Name]; - if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ -#if _USE_LFN /* LFN configuration */ - a = dir[DIR_Attr] & AM_MASK; - if (c == 0xE5 || (!_FS_RPATH && c == '.') || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ - ord = 0xFF; - } else { - if (a == AM_LFN) { /* An LFN entry is found */ - if (c & 0x40) { /* Is it start of LFN sequence? */ - sum = dir[LDIR_Chksum]; - c &= 0xBF; ord = c; - dj->lfn_idx = dj->index; - } - /* Check LFN validity and capture it */ - ord = (c == ord && sum == dir[LDIR_Chksum] && pick_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF; - } else { /* An SFN entry is found */ - if (ord || sum != sum_sfn(dir)) /* Is there a valid LFN? */ - dj->lfn_idx = 0xFFFF; /* It has no LFN. */ - break; - } - } -#else /* Non LFN configuration */ - if (c != 0xE5 && (_FS_RPATH || c != '.') && !(dir[DIR_Attr] & AM_VOL)) /* Is it a valid entry? */ - break; + res = FR_NO_FILE; + + while ( dj->sect ) + { + res = move_window( dj->fs, dj->sect ); + + if ( res != FR_OK ) + { + break; + } + + dir = dj->dir; /* Ptr to the directory entry of current index */ + c = dir[DIR_Name]; + + if ( c == 0 ) + { + res = FR_NO_FILE; /* Reached to end of table */ + break; + } + +#if _USE_LFN /* LFN configuration */ + a = dir[DIR_Attr] & AM_MASK; + + if ( c == 0xE5 || ( !_FS_RPATH && c == '.' ) || ( ( a & AM_VOL ) && a != AM_LFN ) ) /* An entry without valid data */ + { + ord = 0xFF; + } + else + { + if ( a == AM_LFN ) /* An LFN entry is found */ + { + if ( c & 0x40 ) /* Is it start of LFN sequence? */ + { + sum = dir[LDIR_Chksum]; + c &= 0xBF; ord = c; + dj->lfn_idx = dj->index; + } + + /* Check LFN validity and capture it */ + ord = ( c == ord && sum == dir[LDIR_Chksum] && pick_lfn( dj->lfn, dir ) ) ? ord - 1 : 0xFF; + } + else /* An SFN entry is found */ + { + if ( ord || sum != sum_sfn( dir ) ) /* Is there a valid LFN? */ + { + dj->lfn_idx = 0xFFFF; /* It has no LFN. */ + } + + break; + } + } + +#else /* Non LFN configuration */ + + if ( c != 0xE5 && ( _FS_RPATH || c != '.' ) && !( dir[DIR_Attr] & AM_VOL ) ) /* Is it a valid entry? */ + { + break; + } + #endif - res = dir_next(dj, 0); /* Next entry */ - if (res != FR_OK) break; - } + res = dir_next( dj, 0 ); /* Next entry */ - if (res != FR_OK) dj->sect = 0; + if ( res != FR_OK ) + { + break; + } + } - return res; + if ( res != FR_OK ) + { + dj->sect = 0; + } + + return res; } #endif @@ -1228,102 +1671,178 @@ FRESULT dir_read ( /*-----------------------------------------------------------------------*/ #if !_FS_READONLY static -FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many SFN collision, FR_DISK_ERR:Disk error */ - DIR *dj /* Target directory with object name to be created */ +FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many SFN collision, FR_DISK_ERR:Disk error */ + DIR *dj /* Target directory with object name to be created */ ) { - FRESULT res; - BYTE c, *dir; -#if _USE_LFN /* LFN configuration */ - WORD n, ne, is; - BYTE sn[12], *fn, sum; - WCHAR *lfn; + FRESULT res; + BYTE c, *dir; +#if _USE_LFN /* LFN configuration */ + WORD n, ne, is; + BYTE sn[12], *fn, sum; + WCHAR *lfn; - fn = dj->fn; lfn = dj->lfn; - mem_cpy(sn, fn, 12); + fn = dj->fn; lfn = dj->lfn; + mem_cpy( sn, fn, 12 ); - if (_FS_RPATH && (sn[NS] & NS_DOT)) /* Cannot create dot entry */ - return FR_INVALID_NAME; + if ( _FS_RPATH && ( sn[NS] & NS_DOT ) ) /* Cannot create dot entry */ + { + return FR_INVALID_NAME; + } - if (sn[NS] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ - fn[NS] = 0; dj->lfn = 0; /* Find only SFN */ - for (n = 1; n < 100; n++) { - gen_numname(fn, sn, lfn, n); /* Generate a numbered name */ - res = dir_find(dj); /* Check if the name collides with existing SFN */ - if (res != FR_OK) break; - } - if (n == 100) return FR_DENIED; /* Abort if too many collisions */ - if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */ - fn[NS] = sn[NS]; dj->lfn = lfn; - } + if ( sn[NS] & NS_LOSS ) /* When LFN is out of 8.3 format, generate a numbered name */ + { + fn[NS] = 0; dj->lfn = 0; /* Find only SFN */ - if (sn[NS] & NS_LFN) { /* When LFN is to be created, reserve an SFN + LFN entries. */ - for (ne = 0; lfn[ne]; ne++) ; - ne = (ne + 25) / 13; - } else { /* Otherwise reserve only an SFN entry. */ - ne = 1; - } + for ( n = 1; n < 100; n++ ) + { + gen_numname( fn, sn, lfn, n ); /* Generate a numbered name */ + res = dir_find( dj ); /* Check if the name collides with existing SFN */ - /* Reserve contiguous entries */ - res = dir_sdi(dj, 0); - if (res != FR_OK) return res; - n = is = 0; - do { - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - c = *dj->dir; /* Check the entry status */ - if (c == 0xE5 || c == 0) { /* Is it a blank entry? */ - if (n == 0) is = dj->index; /* First index of the contiguous entry */ - if (++n == ne) break; /* A contiguous entry that required count is found */ - } else { - n = 0; /* Not a blank entry. Restart to search */ - } - res = dir_next(dj, 1); /* Next entry with table stretch */ - } while (res == FR_OK); + if ( res != FR_OK ) + { + break; + } + } - if (res == FR_OK && ne > 1) { /* Initialize LFN entry if needed */ - res = dir_sdi(dj, is); - if (res == FR_OK) { - sum = sum_sfn(dj->fn); /* Sum of the SFN tied to the LFN */ - ne--; - do { /* Store LFN entries in bottom first */ - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - fit_lfn(dj->lfn, dj->dir, (BYTE)ne, sum); - dj->fs->wflag = 1; - res = dir_next(dj, 0); /* Next entry */ - } while (res == FR_OK && --ne); - } - } + if ( n == 100 ) + { + return FR_DENIED; /* Abort if too many collisions */ + } + + if ( res != FR_NO_FILE ) + { + return res; /* Abort if the result is other than 'not collided' */ + } + + fn[NS] = sn[NS]; dj->lfn = lfn; + } + + if ( sn[NS] & NS_LFN ) /* When LFN is to be created, reserve an SFN + LFN entries. */ + { + for ( ne = 0; lfn[ne]; ne++ ) ; + + ne = ( ne + 25 ) / 13; + } + else /* Otherwise reserve only an SFN entry. */ + { + ne = 1; + } + + /* Reserve contiguous entries */ + res = dir_sdi( dj, 0 ); + + if ( res != FR_OK ) + { + return res; + } + + n = is = 0; + + do + { + res = move_window( dj->fs, dj->sect ); + + if ( res != FR_OK ) + { + break; + } + + c = *dj->dir; /* Check the entry status */ + + if ( c == 0xE5 || c == 0 ) /* Is it a blank entry? */ + { + if ( n == 0 ) + { + is = dj->index; /* First index of the contiguous entry */ + } + + if ( ++n == ne ) + { + break; /* A contiguous entry that required count is found */ + } + } + else + { + n = 0; /* Not a blank entry. Restart to search */ + } + + res = dir_next( dj, 1 ); /* Next entry with table stretch */ + } + while ( res == FR_OK ); + + if ( res == FR_OK && ne > 1 ) /* Initialize LFN entry if needed */ + { + res = dir_sdi( dj, is ); + + if ( res == FR_OK ) + { + sum = sum_sfn( dj->fn ); /* Sum of the SFN tied to the LFN */ + ne--; + + do /* Store LFN entries in bottom first */ + { + res = move_window( dj->fs, dj->sect ); + + if ( res != FR_OK ) + { + break; + } + + fit_lfn( dj->lfn, dj->dir, ( BYTE )ne, sum ); + dj->fs->wflag = 1; + res = dir_next( dj, 0 ); /* Next entry */ + } + while ( res == FR_OK && --ne ); + } + } + +#else /* Non LFN configuration */ + res = dir_sdi( dj, 0 ); + + if ( res == FR_OK ) + { + do /* Find a blank entry for the SFN */ + { + res = move_window( dj->fs, dj->sect ); + + if ( res != FR_OK ) + { + break; + } + + c = *dj->dir; + + if ( c == 0xE5 || c == 0 ) + { + break; /* Is it a blank entry? */ + } + + res = dir_next( dj, 1 ); /* Next entry with table stretch */ + } + while ( res == FR_OK ); + } -#else /* Non LFN configuration */ - res = dir_sdi(dj, 0); - if (res == FR_OK) { - do { /* Find a blank entry for the SFN */ - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - c = *dj->dir; - if (c == 0xE5 || c == 0) break; /* Is it a blank entry? */ - res = dir_next(dj, 1); /* Next entry with table stretch */ - } while (res == FR_OK); - } #endif - if (res == FR_OK) { /* Initialize the SFN entry */ - res = move_window(dj->fs, dj->sect); - if (res == FR_OK) { - dir = dj->dir; - mem_set(dir, 0, 32); /* Clean the entry */ - mem_cpy(dir, dj->fn, 11); /* Put SFN */ + if ( res == FR_OK ) /* Initialize the SFN entry */ + { + res = move_window( dj->fs, dj->sect ); + + if ( res == FR_OK ) + { + dir = dj->dir; + mem_set( dir, 0, 32 ); /* Clean the entry */ + mem_cpy( dir, dj->fn, 11 ); /* Put SFN */ #if _USE_LFN - dir[DIR_NTres] = *(dj->fn+NS) & (NS_BODY | NS_EXT); /* Put NT flag */ + dir[DIR_NTres] = *( dj->fn + NS ) & ( NS_BODY | NS_EXT ); /* Put NT flag */ #endif - dj->fs->wflag = 1; - } - } + dj->fs->wflag = 1; + } + } - return res; + return res; } #endif /* !_FS_READONLY */ @@ -1335,40 +1854,64 @@ FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many /*-----------------------------------------------------------------------*/ #if !_FS_READONLY && !_FS_MINIMIZE static -FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ - DIR *dj /* Directory object pointing the entry to be removed */ +FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ + DIR *dj /* Directory object pointing the entry to be removed */ ) { - FRESULT res; -#if _USE_LFN /* LFN configuration */ - WORD i; + FRESULT res; +#if _USE_LFN /* LFN configuration */ + WORD i; - i = dj->index; /* SFN index */ - res = dir_sdi(dj, (WORD)((dj->lfn_idx == 0xFFFF) ? i : dj->lfn_idx)); /* Goto the SFN or top of the LFN entries */ - if (res == FR_OK) { - do { - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - *dj->dir = 0xE5; /* Mark the entry "deleted" */ - dj->fs->wflag = 1; - if (dj->index >= i) break; /* When reached SFN, all entries of the object has been deleted. */ - res = dir_next(dj, 0); /* Next entry */ - } while (res == FR_OK); - if (res == FR_NO_FILE) res = FR_INT_ERR; - } + i = dj->index; /* SFN index */ + res = dir_sdi( dj, ( WORD )( ( dj->lfn_idx == 0xFFFF ) ? i : + dj->lfn_idx ) ); /* Goto the SFN or top of the LFN entries */ + + if ( res == FR_OK ) + { + do + { + res = move_window( dj->fs, dj->sect ); + + if ( res != FR_OK ) + { + break; + } + + *dj->dir = 0xE5; /* Mark the entry "deleted" */ + dj->fs->wflag = 1; + + if ( dj->index >= i ) + { + break; /* When reached SFN, all entries of the object has been deleted. */ + } + + res = dir_next( dj, 0 ); /* Next entry */ + } + while ( res == FR_OK ); + + if ( res == FR_NO_FILE ) + { + res = FR_INT_ERR; + } + } + +#else /* Non LFN configuration */ + res = dir_sdi( dj, dj->index ); + + if ( res == FR_OK ) + { + res = move_window( dj->fs, dj->sect ); + + if ( res == FR_OK ) + { + *dj->dir = 0xE5; /* Mark the entry "deleted" */ + dj->fs->wflag = 1; + } + } -#else /* Non LFN configuration */ - res = dir_sdi(dj, dj->index); - if (res == FR_OK) { - res = move_window(dj->fs, dj->sect); - if (res == FR_OK) { - *dj->dir = 0xE5; /* Mark the entry "deleted" */ - dj->fs->wflag = 1; - } - } #endif - return res; + return res; } #endif /* !_FS_READONLY */ @@ -1381,208 +1924,381 @@ FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ static FRESULT create_name ( - DIR *dj, /* Pointer to the directory object */ - const TCHAR **path /* Pointer to pointer to the segment in the path string */ + DIR *dj, /* Pointer to the directory object */ + const TCHAR **path /* Pointer to pointer to the segment in the path string */ ) { #ifdef _EXCVT - static const BYTE excvt[] = _EXCVT; /* Upper conversion table for extended chars */ + static const BYTE excvt[] = _EXCVT; /* Upper conversion table for extended chars */ #endif -#if _USE_LFN /* LFN configuration */ - BYTE b, cf; - WCHAR w, *lfn; - UINT i, ni, si, di; - const TCHAR *p; +#if _USE_LFN /* LFN configuration */ + BYTE b, cf; + WCHAR w, *lfn; + UINT i, ni, si, di; + const TCHAR *p; + + /* Create LFN in Unicode */ + si = di = 0; + p = *path; + lfn = dj->lfn; + + for ( ;; ) + { + w = p[si++]; /* Get a character */ + + if ( w < ' ' || w == '/' || w == '\\' ) + { + break; /* Break on end of segment */ + } + + if ( di >= _MAX_LFN ) /* Reject too long name */ + { + return FR_INVALID_NAME; + } - /* Create LFN in Unicode */ - si = di = 0; - p = *path; - lfn = dj->lfn; - for (;;) { - w = p[si++]; /* Get a character */ - if (w < ' ' || w == '/' || w == '\\') break; /* Break on end of segment */ - if (di >= _MAX_LFN) /* Reject too long name */ - return FR_INVALID_NAME; #if !_LFN_UNICODE - w &= 0xFF; - if (IsDBCS1(w)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ - b = (BYTE)p[si++]; /* Get 2nd byte */ - if (!IsDBCS2(b)) - return FR_INVALID_NAME; /* Reject invalid sequence */ - w = (w << 8) + b; /* Create a DBC */ - } - w = ff_convert(w, 1); /* Convert ANSI/OEM to Unicode */ - if (!w) return FR_INVALID_NAME; /* Reject invalid code */ + w &= 0xFF; + + if ( IsDBCS1( w ) ) /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ + { + b = ( BYTE )p[si++]; /* Get 2nd byte */ + + if ( !IsDBCS2( b ) ) + { + return FR_INVALID_NAME; /* Reject invalid sequence */ + } + + w = ( w << 8 ) + b; /* Create a DBC */ + } + + w = ff_convert( w, 1 ); /* Convert ANSI/OEM to Unicode */ + + if ( !w ) + { + return FR_INVALID_NAME; /* Reject invalid code */ + } + #endif - if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) /* Reject illegal chars for LFN */ - return FR_INVALID_NAME; - lfn[di++] = w; /* Store the Unicode char */ - } - *path = &p[si]; /* Return pointer to the next segment */ - cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ + + if ( w < 0x80 && chk_chr( "\"*:<>\?|\x7F", w ) ) /* Reject illegal chars for LFN */ + { + return FR_INVALID_NAME; + } + + lfn[di++] = w; /* Store the Unicode char */ + } + + *path = &p[si]; /* Return pointer to the next segment */ + cf = ( w < ' ' ) ? NS_LAST : 0; /* Set last segment flag if end of path */ #if _FS_RPATH - if ((di == 1 && lfn[di-1] == '.') || /* Is this a dot entry? */ - (di == 2 && lfn[di-1] == '.' && lfn[di-2] == '.')) { - lfn[di] = 0; - for (i = 0; i < 11; i++) - dj->fn[i] = (i < di) ? '.' : ' '; - dj->fn[i] = cf | NS_DOT; /* This is a dot entry */ - return FR_OK; - } + + if ( ( di == 1 && lfn[di - 1] == '.' ) || /* Is this a dot entry? */ + ( di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.' ) ) + { + lfn[di] = 0; + + for ( i = 0; i < 11; i++ ) + { + dj->fn[i] = ( i < di ) ? '.' : ' '; + } + + dj->fn[i] = cf | NS_DOT; /* This is a dot entry */ + return FR_OK; + } + #endif - while (di) { /* Strip trailing spaces and dots */ - w = lfn[di-1]; - if (w != ' ' && w != '.') break; - di--; - } - if (!di) return FR_INVALID_NAME; /* Reject nul string */ - lfn[di] = 0; /* LFN is created */ + while ( di ) /* Strip trailing spaces and dots */ + { + w = lfn[di - 1]; - /* Create SFN in directory form */ - mem_set(dj->fn, ' ', 11); - for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; /* Strip leading spaces and dots */ - if (si) cf |= NS_LOSS | NS_LFN; - while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */ + if ( w != ' ' && w != '.' ) + { + break; + } - b = i = 0; ni = 8; - for (;;) { - w = lfn[si++]; /* Get an LFN char */ - if (!w) break; /* Break on end of the LFN */ - if (w == ' ' || (w == '.' && si != di)) { /* Remove spaces and dots */ - cf |= NS_LOSS | NS_LFN; continue; - } + di--; + } - if (i >= ni || si == di) { /* Extension or end of SFN */ - if (ni == 11) { /* Long extension */ - cf |= NS_LOSS | NS_LFN; break; - } - if (si != di) cf |= NS_LOSS | NS_LFN; /* Out of 8.3 format */ - if (si > di) break; /* No extension */ - si = di; i = 8; ni = 11; /* Enter extension section */ - b <<= 2; continue; - } + if ( !di ) + { + return FR_INVALID_NAME; /* Reject nul string */ + } - if (w >= 0x80) { /* Non ASCII char */ + lfn[di] = 0; /* LFN is created */ + + /* Create SFN in directory form */ + mem_set( dj->fn, ' ', 11 ); + + for ( si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++ ) ; /* Strip leading spaces and dots */ + + if ( si ) + { + cf |= NS_LOSS | NS_LFN; + } + + while ( di && lfn[di - 1] != '.' ) + { + di--; /* Find extension (di<=si: no extension) */ + } + + b = i = 0; ni = 8; + + for ( ;; ) + { + w = lfn[si++]; /* Get an LFN char */ + + if ( !w ) + { + break; /* Break on end of the LFN */ + } + + if ( w == ' ' || ( w == '.' && si != di ) ) /* Remove spaces and dots */ + { + cf |= NS_LOSS | NS_LFN; continue; + } + + if ( i >= ni || si == di ) /* Extension or end of SFN */ + { + if ( ni == 11 ) /* Long extension */ + { + cf |= NS_LOSS | NS_LFN; break; + } + + if ( si != di ) + { + cf |= NS_LOSS | NS_LFN; /* Out of 8.3 format */ + } + + if ( si > di ) + { + break; /* No extension */ + } + + si = di; i = 8; ni = 11; /* Enter extension section */ + b <<= 2; continue; + } + + if ( w >= 0x80 ) /* Non ASCII char */ + { #ifdef _EXCVT - w = ff_convert(w, 0); /* Unicode -> OEM code */ - if (w) w = excvt[w - 0x80]; /* Convert extended char to upper (SBCS) */ + w = ff_convert( w, 0 ); /* Unicode -> OEM code */ + + if ( w ) + { + w = excvt[w - 0x80]; /* Convert extended char to upper (SBCS) */ + } + #else - w = ff_convert(ff_wtoupper(w), 0); /* Upper converted Unicode -> OEM code */ + w = ff_convert( ff_wtoupper( w ), 0 ); /* Upper converted Unicode -> OEM code */ #endif - cf |= NS_LFN; /* Force create LFN entry */ - } + cf |= NS_LFN; /* Force create LFN entry */ + } - if (_DF1S && w >= 0x100) { /* Double byte char (always false on SBCS cfg) */ - if (i >= ni - 1) { - cf |= NS_LOSS | NS_LFN; i = ni; continue; - } - dj->fn[i++] = (BYTE)(w >> 8); - } else { /* Single byte char */ - if (!w || chk_chr("+,;=[]", w)) { /* Replace illegal chars for SFN */ - w = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */ - } else { - if (IsUpper(w)) { /* ASCII large capital */ - b |= 2; - } else { - if (IsLower(w)) { /* ASCII small capital */ - b |= 1; w -= 0x20; - } - } - } - } - dj->fn[i++] = (BYTE)w; - } + if ( _DF1S && w >= 0x100 ) /* Double byte char (always false on SBCS cfg) */ + { + if ( i >= ni - 1 ) + { + cf |= NS_LOSS | NS_LFN; i = ni; continue; + } - if (dj->fn[0] == 0xE5) dj->fn[0] = 0x05; /* If the first char collides with deleted mark, replace it with 0x05 */ + dj->fn[i++] = ( BYTE )( w >> 8 ); + } + else /* Single byte char */ + { + if ( !w || chk_chr( "+,;=[]", w ) ) /* Replace illegal chars for SFN */ + { + w = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */ + } + else + { + if ( IsUpper( w ) ) /* ASCII large capital */ + { + b |= 2; + } + else + { + if ( IsLower( w ) ) /* ASCII small capital */ + { + b |= 1; w -= 0x20; + } + } + } + } - if (ni == 8) b <<= 2; - if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) /* Create LFN entry when there are composite capitals */ - cf |= NS_LFN; - if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended char, NT flags are created */ - if ((b & 0x03) == 0x01) cf |= NS_EXT; /* NT flag (Extension has only small capital) */ - if ((b & 0x0C) == 0x04) cf |= NS_BODY; /* NT flag (Filename has only small capital) */ - } + dj->fn[i++] = ( BYTE )w; + } - dj->fn[NS] = cf; /* SFN is created */ + if ( dj->fn[0] == 0xE5 ) + { + dj->fn[0] = 0x05; /* If the first char collides with deleted mark, replace it with 0x05 */ + } - return FR_OK; + if ( ni == 8 ) + { + b <<= 2; + } + + if ( ( b & 0x0C ) == 0x0C || ( b & 0x03 ) == 0x03 ) /* Create LFN entry when there are composite capitals */ + { + cf |= NS_LFN; + } + + if ( !( cf & NS_LFN ) ) /* When LFN is in 8.3 format without extended char, NT flags are created */ + { + if ( ( b & 0x03 ) == 0x01 ) + { + cf |= NS_EXT; /* NT flag (Extension has only small capital) */ + } + + if ( ( b & 0x0C ) == 0x04 ) + { + cf |= NS_BODY; /* NT flag (Filename has only small capital) */ + } + } + + dj->fn[NS] = cf; /* SFN is created */ + + return FR_OK; -#else /* Non-LFN configuration */ - BYTE b, c, d, *sfn; - UINT ni, si, i; - const char *p; +#else /* Non-LFN configuration */ + BYTE b, c, d, *sfn; + UINT ni, si, i; + const char *p; - /* Create file name in directory form */ - sfn = dj->fn; - mem_set(sfn, ' ', 11); - si = i = b = 0; ni = 8; - p = *path; + /* Create file name in directory form */ + sfn = dj->fn; + mem_set( sfn, ' ', 11 ); + si = i = b = 0; ni = 8; + p = *path; #if _FS_RPATH - if (p[si] == '.') { /* Is this a dot entry? */ - for (;;) { - c = (BYTE)p[si++]; - if (c != '.' || si >= 3) break; - sfn[i++] = c; - } - if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME; - *path = &p[si]; /* Return pointer to the next segment */ - sfn[NS] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of path */ - return FR_OK; - } + + if ( p[si] == '.' ) /* Is this a dot entry? */ + { + for ( ;; ) + { + c = ( BYTE )p[si++]; + + if ( c != '.' || si >= 3 ) + { + break; + } + + sfn[i++] = c; + } + + if ( c != '/' && c != '\\' && c > ' ' ) + { + return FR_INVALID_NAME; + } + + *path = &p[si]; /* Return pointer to the next segment */ + sfn[NS] = ( c <= ' ' ) ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of path */ + return FR_OK; + } + #endif - for (;;) { - c = (BYTE)p[si++]; - if (c <= ' ' || c == '/' || c == '\\') break; /* Break on end of segment */ - if (c == '.' || i >= ni) { - if (ni != 8 || c != '.') return FR_INVALID_NAME; - i = 8; ni = 11; - b <<= 2; continue; - } - if (c >= 0x80) { /* Extended char? */ - b |= 3; /* Eliminate NT flag */ + + for ( ;; ) + { + c = ( BYTE )p[si++]; + + if ( c <= ' ' || c == '/' || c == '\\' ) + { + break; /* Break on end of segment */ + } + + if ( c == '.' || i >= ni ) + { + if ( ni != 8 || c != '.' ) + { + return FR_INVALID_NAME; + } + + i = 8; ni = 11; + b <<= 2; continue; + } + + if ( c >= 0x80 ) /* Extended char? */ + { + b |= 3; /* Eliminate NT flag */ #ifdef _EXCVT - c = excvt[c-0x80]; /* Upper conversion (SBCS) */ + c = excvt[c - 0x80]; /* Upper conversion (SBCS) */ #else -#if !_DF1S /* ASCII only cfg */ - return FR_INVALID_NAME; +#if !_DF1S /* ASCII only cfg */ + return FR_INVALID_NAME; #endif #endif - } - if (IsDBCS1(c)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ - d = (BYTE)p[si++]; /* Get 2nd byte */ - if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */ - return FR_INVALID_NAME; - sfn[i++] = c; - sfn[i++] = d; - } else { /* Single byte code */ - if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) /* Reject illegal chrs for SFN */ - return FR_INVALID_NAME; - if (IsUpper(c)) { /* ASCII large capital? */ - b |= 2; - } else { - if (IsLower(c)) { /* ASCII small capital? */ - b |= 1; c -= 0x20; - } - } - sfn[i++] = c; - } - } - *path = &p[si]; /* Return pointer to the next segment */ - c = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ + } - if (!i) return FR_INVALID_NAME; /* Reject nul string */ - if (sfn[0] == 0xE5) sfn[0] = 0x05; /* When first char collides with 0xE5, replace it with 0x05 */ + if ( IsDBCS1( c ) ) /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ + { + d = ( BYTE )p[si++]; /* Get 2nd byte */ - if (ni == 8) b <<= 2; - if ((b & 0x03) == 0x01) c |= NS_EXT; /* NT flag (Name extension has only small capital) */ - if ((b & 0x0C) == 0x04) c |= NS_BODY; /* NT flag (Name body has only small capital) */ + if ( !IsDBCS2( d ) || i >= ni - 1 ) /* Reject invalid DBC */ + { + return FR_INVALID_NAME; + } - sfn[NS] = c; /* Store NT flag, File name is created */ + sfn[i++] = c; + sfn[i++] = d; + } + else /* Single byte code */ + { + if ( chk_chr( "\"*+,:;<=>\?[]|\x7F", c ) ) /* Reject illegal chrs for SFN */ + { + return FR_INVALID_NAME; + } - return FR_OK; + if ( IsUpper( c ) ) /* ASCII large capital? */ + { + b |= 2; + } + else + { + if ( IsLower( c ) ) /* ASCII small capital? */ + { + b |= 1; c -= 0x20; + } + } + + sfn[i++] = c; + } + } + + *path = &p[si]; /* Return pointer to the next segment */ + c = ( c <= ' ' ) ? NS_LAST : 0; /* Set last segment flag if end of path */ + + if ( !i ) + { + return FR_INVALID_NAME; /* Reject nul string */ + } + + if ( sfn[0] == 0xE5 ) + { + sfn[0] = 0x05; /* When first char collides with 0xE5, replace it with 0x05 */ + } + + if ( ni == 8 ) + { + b <<= 2; + } + + if ( ( b & 0x03 ) == 0x01 ) + { + c |= NS_EXT; /* NT flag (Name extension has only small capital) */ + } + + if ( ( b & 0x0C ) == 0x04 ) + { + c |= NS_BODY; /* NT flag (Name body has only small capital) */ + } + + sfn[NS] = c; /* Store NT flag, File name is created */ + + return FR_OK; #endif } @@ -1594,78 +2310,151 @@ FRESULT create_name ( /*-----------------------------------------------------------------------*/ #if _FS_MINIMIZE <= 1 static -void get_fileinfo ( /* No return code */ - DIR *dj, /* Pointer to the directory object */ - FILINFO *fno /* Pointer to the file information to be filled */ +void get_fileinfo ( /* No return code */ + DIR *dj, /* Pointer to the directory object */ + FILINFO *fno /* Pointer to the file information to be filled */ ) { - UINT i; - BYTE nt, *dir; - TCHAR *p, c; + UINT i; + BYTE nt, *dir; + TCHAR *p, c; - p = fno->fname; - if (dj->sect) { - dir = dj->dir; - nt = dir[DIR_NTres]; /* NT flag */ - for (i = 0; i < 8; i++) { /* Copy name body */ - c = dir[i]; - if (c == ' ') break; - if (c == 0x05) c = (TCHAR)0xE5; - if (_USE_LFN && (nt & NS_BODY) && IsUpper(c)) c += 0x20; + p = fno->fname; + + if ( dj->sect ) + { + dir = dj->dir; + nt = dir[DIR_NTres]; /* NT flag */ + + for ( i = 0; i < 8; i++ ) /* Copy name body */ + { + c = dir[i]; + + if ( c == ' ' ) + { + break; + } + + if ( c == 0x05 ) + { + c = ( TCHAR )0xE5; + } + + if ( _USE_LFN && ( nt & NS_BODY ) && IsUpper( c ) ) + { + c += 0x20; + } + #if _LFN_UNICODE - if (IsDBCS1(c) && i < 7 && IsDBCS2(dir[i+1])) - c = (c << 8) | dir[++i]; - c = ff_convert(c, 1); - if (!c) c = '?'; + + if ( IsDBCS1( c ) && i < 7 && IsDBCS2( dir[i + 1] ) ) + { + c = ( c << 8 ) | dir[++i]; + } + + c = ff_convert( c, 1 ); + + if ( !c ) + { + c = '?'; + } + #endif - *p++ = c; - } - if (dir[8] != ' ') { /* Copy name extension */ - *p++ = '.'; - for (i = 8; i < 11; i++) { - c = dir[i]; - if (c == ' ') break; - if (_USE_LFN && (nt & NS_EXT) && IsUpper(c)) c += 0x20; + *p++ = c; + } + + if ( dir[8] != ' ' ) /* Copy name extension */ + { + *p++ = '.'; + + for ( i = 8; i < 11; i++ ) + { + c = dir[i]; + + if ( c == ' ' ) + { + break; + } + + if ( _USE_LFN && ( nt & NS_EXT ) && IsUpper( c ) ) + { + c += 0x20; + } + #if _LFN_UNICODE - if (IsDBCS1(c) && i < 10 && IsDBCS2(dir[i+1])) - c = (c << 8) | dir[++i]; - c = ff_convert(c, 1); - if (!c) c = '?'; + + if ( IsDBCS1( c ) && i < 10 && IsDBCS2( dir[i + 1] ) ) + { + c = ( c << 8 ) | dir[++i]; + } + + c = ff_convert( c, 1 ); + + if ( !c ) + { + c = '?'; + } + #endif - *p++ = c; - } - } - fno->fattrib = dir[DIR_Attr]; /* Attribute */ - fno->fsize = LD_DWORD(dir+DIR_FileSize); /* Size */ - fno->fdate = LD_WORD(dir+DIR_WrtDate); /* Date */ - fno->ftime = LD_WORD(dir+DIR_WrtTime); /* Time */ - fno->clust = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) - | LD_WORD(dir+DIR_FstClusLO); - } - *p = 0; /* Terminate SFN str by a \0 */ + *p++ = c; + } + } + + fno->fattrib = dir[DIR_Attr]; /* Attribute */ + fno->fsize = LD_DWORD( dir + DIR_FileSize ); /* Size */ + fno->fdate = LD_WORD( dir + DIR_WrtDate ); /* Date */ + fno->ftime = LD_WORD( dir + DIR_WrtTime ); /* Time */ + fno->clust = ( ( DWORD )LD_WORD( dir + DIR_FstClusHI ) << 16 ) + | LD_WORD( dir + DIR_FstClusLO ); + } + + *p = 0; /* Terminate SFN str by a \0 */ #if _USE_LFN - if (fno->lfname && fno->lfsize) { - TCHAR *tp = fno->lfname; - WCHAR w, *lfn; - i = 0; - if (dj->sect && dj->lfn_idx != 0xFFFF) {/* Get LFN if available */ - lfn = dj->lfn; - while ((w = *lfn++) != 0) { /* Get an LFN char */ + if ( fno->lfname && fno->lfsize ) + { + TCHAR *tp = fno->lfname; + WCHAR w, *lfn; + + i = 0; + + if ( dj->sect && dj->lfn_idx != 0xFFFF ) /* Get LFN if available */ + { + lfn = dj->lfn; + + while ( ( w = *lfn++ ) != 0 ) /* Get an LFN char */ + { #if !_LFN_UNICODE - w = ff_convert(w, 0); /* Unicode -> OEM conversion */ - if (!w) { i = 0; break; } /* Could not convert, no LFN */ - if (_DF1S && w >= 0x100) /* Put 1st byte if it is a DBC (always false on SBCS cfg) */ - tp[i++] = (TCHAR)(w >> 8); + w = ff_convert( w, 0 ); /* Unicode -> OEM conversion */ + + if ( !w ) + { + i = 0; /* Could not convert, no LFN */ + break; + } + + if ( _DF1S && w >= 0x100 ) /* Put 1st byte if it is a DBC (always false on SBCS cfg) */ + { + tp[i++] = ( TCHAR )( w >> 8 ); + } + #endif - if (i >= fno->lfsize - 1) { i = 0; break; } /* Buffer overflow, no LFN */ - tp[i++] = (TCHAR)w; - } - } - tp[i] = 0; /* Terminate the LFN str by a \0 */ - } + + if ( i >= fno->lfsize - 1 ) + { + i = 0; /* Buffer overflow, no LFN */ + break; + } + + tp[i++] = ( TCHAR )w; + } + } + + tp[i] = 0; /* Terminate the LFN str by a \0 */ + } + #endif } #endif /* _FS_MINIMIZE <= 1 */ @@ -1678,59 +2467,102 @@ void get_fileinfo ( /* No return code */ /*-----------------------------------------------------------------------*/ static -FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ - DIR *dj, /* Directory object to return last directory and found object */ - const TCHAR *path /* Full-path string to find a file or directory */ +FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ + DIR *dj, /* Directory object to return last directory and found object */ + const TCHAR *path /* Full-path string to find a file or directory */ ) { - FRESULT res; - BYTE *dir, ns; + FRESULT res; + BYTE *dir, ns; #if _FS_RPATH - if (*path == '/' || *path == '\\') { /* There is a heading separator */ - path++; dj->sclust = 0; /* Strip it and start from the root dir */ - } else { /* No heading separator */ - dj->sclust = dj->fs->cdir; /* Start from the current dir */ - } + + if ( *path == '/' || *path == '\\' ) /* There is a heading separator */ + { + path++; dj->sclust = 0; /* Strip it and start from the root dir */ + } + else /* No heading separator */ + { + dj->sclust = dj->fs->cdir; /* Start from the current dir */ + } + #else - if (*path == '/' || *path == '\\') /* Strip heading separator if exist */ - path++; - dj->sclust = 0; /* Start from the root dir */ + + if ( *path == '/' || *path == '\\' ) /* Strip heading separator if exist */ + { + path++; + } + + dj->sclust = 0; /* Start from the root dir */ #endif - if ((UINT)*path < ' ') { /* Nul path means the start directory itself */ - res = dir_sdi(dj, 0); - dj->dir = 0; + if ( ( UINT )*path < ' ' ) /* Nul path means the start directory itself */ + { + res = dir_sdi( dj, 0 ); + dj->dir = 0; - } else { /* Follow path */ - for (;;) { - res = create_name(dj, &path); /* Get a segment */ - if (res != FR_OK) break; - res = dir_find(dj); /* Find it */ - ns = *(dj->fn+NS); - if (res != FR_OK) { /* Failed to find the object */ - if (res != FR_NO_FILE) break; /* Abort if any hard error occured */ - /* Object not found */ - if (_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exit */ - dj->sclust = 0; dj->dir = 0; /* It is the root dir */ - res = FR_OK; - if (!(ns & NS_LAST)) continue; - } else { /* Could not find the object */ - if (!(ns & NS_LAST)) res = FR_NO_PATH; - } - break; - } - if (ns & NS_LAST) break; /* Last segment match. Function completed. */ - dir = dj->dir; /* There is next segment. Follow the sub directory */ - if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */ - res = FR_NO_PATH; break; - } - dj->sclust = LD_CLUST(dir); - } - } + } + else /* Follow path */ + { + for ( ;; ) + { + res = create_name( dj, &path ); /* Get a segment */ - return res; + if ( res != FR_OK ) + { + break; + } + + res = dir_find( dj ); /* Find it */ + ns = *( dj->fn + NS ); + + if ( res != FR_OK ) /* Failed to find the object */ + { + if ( res != FR_NO_FILE ) + { + break; /* Abort if any hard error occured */ + } + + /* Object not found */ + if ( _FS_RPATH && ( ns & NS_DOT ) ) /* If dot entry is not exit */ + { + dj->sclust = 0; dj->dir = 0; /* It is the root dir */ + res = FR_OK; + + if ( !( ns & NS_LAST ) ) + { + continue; + } + } + else /* Could not find the object */ + { + if ( !( ns & NS_LAST ) ) + { + res = FR_NO_PATH; + } + } + + break; + } + + if ( ns & NS_LAST ) + { + break; /* Last segment match. Function completed. */ + } + + dir = dj->dir; /* There is next segment. Follow the sub directory */ + + if ( !( dir[DIR_Attr] & AM_DIR ) ) /* Cannot follow because it is a file */ + { + res = FR_NO_PATH; break; + } + + dj->sclust = LD_CLUST( dir ); + } + } + + return res; } @@ -1741,22 +2573,33 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ /*-----------------------------------------------------------------------*/ static -BYTE check_fs ( /* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:Disk error */ - FATFS *fs, /* File system object */ - DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ +BYTE check_fs ( /* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:Disk error */ + FATFS *fs, /* File system object */ + DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ ) { - if (disk_read(fs->drv, fs->win, sect, 1) != RES_OK) /* Load boot record */ - return 3; - if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check record signature (always placed at offset 510 even if the sector size is >512) */ - return 2; + if ( disk_read( fs->drv, fs->win, sect, 1 ) != RES_OK ) /* Load boot record */ + { + return 3; + } - if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */ - return 0; - if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146) - return 0; + if ( LD_WORD( &fs->win[BS_55AA] ) != + 0xAA55 ) /* Check record signature (always placed at offset 510 even if the sector size is >512) */ + { + return 2; + } - return 1; + if ( ( LD_DWORD( &fs->win[BS_FilSysType] ) & 0xFFFFFF ) == 0x544146 ) /* Check "FAT" string */ + { + return 0; + } + + if ( ( LD_DWORD( &fs->win[BS_FilSysType32] ) & 0xFFFFFF ) == 0x544146 ) + { + return 0; + } + + return 1; } @@ -1767,161 +2610,268 @@ BYTE check_fs ( /* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:Disk e /*-----------------------------------------------------------------------*/ static -FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ - const TCHAR **path, /* Pointer to pointer to the path name (drive number) */ - FATFS **rfs, /* Pointer to pointer to the found file system object */ - BYTE chk_wp /* !=0: Check media write protection for write access */ +FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ + const TCHAR **path, /* Pointer to pointer to the path name (drive number) */ + FATFS **rfs, /* Pointer to pointer to the found file system object */ + BYTE chk_wp /* !=0: Check media write protection for write access */ ) { - BYTE fmt, b, *tbl; - UINT vol; - DSTATUS stat; - DWORD bsect, fasize, tsect, sysect, nclst, szbfat; - WORD nrsv; - const TCHAR *p = *path; - FATFS *fs; + BYTE fmt, b, *tbl; + UINT vol; + DSTATUS stat; + DWORD bsect, fasize, tsect, sysect, nclst, szbfat; + WORD nrsv; + const TCHAR *p = *path; + FATFS *fs; - /* Get logical drive number from the path name */ - vol = p[0] - '0'; /* Is there a drive number? */ - if (vol <= 9 && p[1] == ':') { /* Found a drive number, get and strip it */ - p += 2; *path = p; /* Return pointer to the path name */ - } else { /* No drive number is given */ + /* Get logical drive number from the path name */ + vol = p[0] - '0'; /* Is there a drive number? */ + + if ( vol <= 9 && p[1] == ':' ) /* Found a drive number, get and strip it */ + { + p += 2; *path = p; /* Return pointer to the path name */ + } + else /* No drive number is given */ + { #if _FS_RPATH - vol = CurrVol; /* Use current drive */ + vol = CurrVol; /* Use current drive */ #else - vol = 0; /* Use drive 0 */ + vol = 0; /* Use drive 0 */ #endif - } + } - /* Check if the logical drive is valid or not */ - if (vol >= _VOLUMES) /* Is the drive number valid? */ - return FR_INVALID_DRIVE; - *rfs = fs = FatFs[vol]; /* Return pointer to the corresponding file system object */ - if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */ + /* Check if the logical drive is valid or not */ + if ( vol >= _VOLUMES ) /* Is the drive number valid? */ + { + return FR_INVALID_DRIVE; + } - ENTER_FF(fs); /* Lock file system */ + *rfs = fs = FatFs[vol]; /* Return pointer to the corresponding file system object */ - if (fs->fs_type) { /* If the logical drive has been mounted */ - stat = disk_status(fs->drv); - if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized (has not been changed), */ + if ( !fs ) + { + return FR_NOT_ENABLED; /* Is the file system object available? */ + } + + ENTER_FF( fs ); /* Lock file system */ + + if ( fs->fs_type ) /* If the logical drive has been mounted */ + { + stat = disk_status( fs->drv ); + + if ( !( stat & STA_NOINIT ) ) /* and the physical drive is kept initialized (has not been changed), */ + { #if !_FS_READONLY - if (chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */ - return FR_WRITE_PROTECTED; + + if ( chk_wp && ( stat & STA_PROTECT ) ) /* Check write protection if needed */ + { + return FR_WRITE_PROTECTED; + } + #endif - return FR_OK; /* The file system object is valid */ - } - } + return FR_OK; /* The file system object is valid */ + } + } - /* The logical drive must be mounted. */ - /* Following code attempts to mount a volume. (analyze BPB and initialize the fs object) */ + /* The logical drive must be mounted. */ + /* Following code attempts to mount a volume. (analyze BPB and initialize the fs object) */ + + fs->fs_type = 0; /* Clear the file system object */ + fs->drv = ( BYTE )LD2PD( vol ); /* Bind the logical drive and a physical drive */ + stat = disk_initialize( fs->drv ); /* Initialize low level disk I/O layer */ + + if ( stat & STA_NOINIT ) /* Check if the initialization succeeded */ + { + return FR_NOT_READY; /* Failed to initialize due to no media or hard error */ + } + +#if _MAX_SS != 512 /* Get disk sector size (variable sector size cfg only) */ + + if ( disk_ioctl( fs->drv, GET_SECTOR_SIZE, &fs->ssize ) != RES_OK ) + { + return FR_DISK_ERR; + } - fs->fs_type = 0; /* Clear the file system object */ - fs->drv = (BYTE)LD2PD(vol); /* Bind the logical drive and a physical drive */ - stat = disk_initialize(fs->drv); /* Initialize low level disk I/O layer */ - if (stat & STA_NOINIT) /* Check if the initialization succeeded */ - return FR_NOT_READY; /* Failed to initialize due to no media or hard error */ -#if _MAX_SS != 512 /* Get disk sector size (variable sector size cfg only) */ - if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &fs->ssize) != RES_OK) - return FR_DISK_ERR; #endif #if !_FS_READONLY - if (chk_wp && (stat & STA_PROTECT)) /* Check disk write protection if needed */ - return FR_WRITE_PROTECTED; + + if ( chk_wp && ( stat & STA_PROTECT ) ) /* Check disk write protection if needed */ + { + return FR_WRITE_PROTECTED; + } + #endif - /* Search FAT partition on the drive. Supports only generic partitionings, FDISK and SFD. */ - fmt = check_fs(fs, bsect = 0); /* Check sector 0 if it is a VBR */ - if (fmt == 1) { /* Not an FAT-VBR, the disk may be partitioned */ - /* Check the partition listed in top of the partition table */ - tbl = &fs->win[MBR_Table + LD2PT(vol) * 16]; /* Partition table */ - if (tbl[4]) { /* Is the partition existing? */ - bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */ - fmt = check_fs(fs, bsect); /* Check the partition */ - } - } - if (fmt == 3) return FR_DISK_ERR; - if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */ + /* Search FAT partition on the drive. Supports only generic partitionings, FDISK and SFD. */ + fmt = check_fs( fs, bsect = 0 ); /* Check sector 0 if it is a VBR */ - /* Following code initializes the file system object */ + if ( fmt == 1 ) /* Not an FAT-VBR, the disk may be partitioned */ + { + /* Check the partition listed in top of the partition table */ + tbl = &fs->win[MBR_Table + LD2PT( vol ) * 16]; /* Partition table */ - if (LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs)) /* (BPB_BytsPerSec must be equal to the physical sector size) */ - return FR_NO_FILESYSTEM; + if ( tbl[4] ) /* Is the partition existing? */ + { + bsect = LD_DWORD( &tbl[8] ); /* Partition offset in LBA */ + fmt = check_fs( fs, bsect ); /* Check the partition */ + } + } - fasize = LD_WORD(fs->win+BPB_FATSz16); /* Number of sectors per FAT */ - if (!fasize) fasize = LD_DWORD(fs->win+BPB_FATSz32); - fs->fsize = fasize; + if ( fmt == 3 ) + { + return FR_DISK_ERR; + } - fs->n_fats = b = fs->win[BPB_NumFATs]; /* Number of FAT copies */ - if (b != 1 && b != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */ - fasize *= b; /* Number of sectors for FAT area */ + if ( fmt ) + { + return FR_NO_FILESYSTEM; /* No FAT volume is found */ + } - fs->csize = b = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */ - if (!b || (b & (b - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */ + /* Following code initializes the file system object */ - fs->n_rootdir = LD_WORD(fs->win+BPB_RootEntCnt); /* Number of root directory entries */ - if (fs->n_rootdir % (SS(fs) / 32)) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be sector aligned) */ + if ( LD_WORD( fs->win + BPB_BytsPerSec ) != SS( fs ) ) /* (BPB_BytsPerSec must be equal to the physical sector size) */ + { + return FR_NO_FILESYSTEM; + } - tsect = LD_WORD(fs->win+BPB_TotSec16); /* Number of sectors on the volume */ - if (!tsect) tsect = LD_DWORD(fs->win+BPB_TotSec32); + fasize = LD_WORD( fs->win + BPB_FATSz16 ); /* Number of sectors per FAT */ - nrsv = LD_WORD(fs->win+BPB_RsvdSecCnt); /* Number of reserved sectors */ - if (!nrsv) return FR_NO_FILESYSTEM; /* (BPB_RsvdSecCnt must not be 0) */ + if ( !fasize ) + { + fasize = LD_DWORD( fs->win + BPB_FATSz32 ); + } - /* Determine the FAT sub type */ - sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / 32); /* RSV+FAT+DIR */ - if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ - nclst = (tsect - sysect) / fs->csize; /* Number of clusters */ - if (!nclst) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ - fmt = FS_FAT12; - if (nclst >= MIN_FAT16) fmt = FS_FAT16; - if (nclst >= MIN_FAT32) fmt = FS_FAT32; + fs->fsize = fasize; - /* Boundaries and Limits */ - fs->n_fatent = nclst + 2; /* Number of FAT entries */ - fs->database = bsect + sysect; /* Data start sector */ - fs->fatbase = bsect + nrsv; /* FAT start sector */ - if (fmt == FS_FAT32) { - if (fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ - fs->dirbase = LD_DWORD(fs->win+BPB_RootClus); /* Root directory start cluster */ - szbfat = fs->n_fatent * 4; /* (Required FAT size) */ - } else { - if (!fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ - fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ - szbfat = (fmt == FS_FAT16) ? /* (Required FAT size) */ - fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); - } - if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) /* (FAT size must not be less than FAT sectors */ - return FR_NO_FILESYSTEM; + fs->n_fats = b = fs->win[BPB_NumFATs]; /* Number of FAT copies */ + + if ( b != 1 && b != 2 ) + { + return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */ + } + + fasize *= b; /* Number of sectors for FAT area */ + + fs->csize = b = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */ + + if ( !b || ( b & ( b - 1 ) ) ) + { + return FR_NO_FILESYSTEM; /* (Must be power of 2) */ + } + + fs->n_rootdir = LD_WORD( fs->win + BPB_RootEntCnt ); /* Number of root directory entries */ + + if ( fs->n_rootdir % ( SS( fs ) / 32 ) ) + { + return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be sector aligned) */ + } + + tsect = LD_WORD( fs->win + BPB_TotSec16 ); /* Number of sectors on the volume */ + + if ( !tsect ) + { + tsect = LD_DWORD( fs->win + BPB_TotSec32 ); + } + + nrsv = LD_WORD( fs->win + BPB_RsvdSecCnt ); /* Number of reserved sectors */ + + if ( !nrsv ) + { + return FR_NO_FILESYSTEM; /* (BPB_RsvdSecCnt must not be 0) */ + } + + /* Determine the FAT sub type */ + sysect = nrsv + fasize + fs->n_rootdir / ( SS( fs ) / 32 ); /* RSV+FAT+DIR */ + + if ( tsect < sysect ) + { + return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + } + + nclst = ( tsect - sysect ) / fs->csize; /* Number of clusters */ + + if ( !nclst ) + { + return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + } + + fmt = FS_FAT12; + + if ( nclst >= MIN_FAT16 ) + { + fmt = FS_FAT16; + } + + if ( nclst >= MIN_FAT32 ) + { + fmt = FS_FAT32; + } + + /* Boundaries and Limits */ + fs->n_fatent = nclst + 2; /* Number of FAT entries */ + fs->database = bsect + sysect; /* Data start sector */ + fs->fatbase = bsect + nrsv; /* FAT start sector */ + + if ( fmt == FS_FAT32 ) + { + if ( fs->n_rootdir ) + { + return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ + } + + fs->dirbase = LD_DWORD( fs->win + BPB_RootClus ); /* Root directory start cluster */ + szbfat = fs->n_fatent * 4; /* (Required FAT size) */ + } + else + { + if ( !fs->n_rootdir ) + { + return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ + } + + fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ + szbfat = ( fmt == FS_FAT16 ) ? /* (Required FAT size) */ + fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + ( fs->n_fatent & 1 ); + } + + if ( fs->fsize < ( szbfat + ( SS( fs ) - 1 ) ) / SS( fs ) ) /* (FAT size must not be less than FAT sectors */ + { + return FR_NO_FILESYSTEM; + } #if !_FS_READONLY - /* Initialize cluster allocation information */ - fs->free_clust = 0xFFFFFFFF; - fs->last_clust = 0; + /* Initialize cluster allocation information */ + fs->free_clust = 0xFFFFFFFF; + fs->last_clust = 0; + + /* Get fsinfo if available */ + if ( fmt == FS_FAT32 ) + { + fs->fsi_flag = 0; + fs->fsi_sector = bsect + LD_WORD( fs->win + BPB_FSInfo ); + + if ( disk_read( fs->drv, fs->win, fs->fsi_sector, 1 ) == RES_OK && + LD_WORD( fs->win + BS_55AA ) == 0xAA55 && + LD_DWORD( fs->win + FSI_LeadSig ) == 0x41615252 && + LD_DWORD( fs->win + FSI_StrucSig ) == 0x61417272 ) + { + fs->last_clust = LD_DWORD( fs->win + FSI_Nxt_Free ); + fs->free_clust = LD_DWORD( fs->win + FSI_Free_Count ); + } + } - /* Get fsinfo if available */ - if (fmt == FS_FAT32) { - fs->fsi_flag = 0; - fs->fsi_sector = bsect + LD_WORD(fs->win+BPB_FSInfo); - if (disk_read(fs->drv, fs->win, fs->fsi_sector, 1) == RES_OK && - LD_WORD(fs->win+BS_55AA) == 0xAA55 && - LD_DWORD(fs->win+FSI_LeadSig) == 0x41615252 && - LD_DWORD(fs->win+FSI_StrucSig) == 0x61417272) { - fs->last_clust = LD_DWORD(fs->win+FSI_Nxt_Free); - fs->free_clust = LD_DWORD(fs->win+FSI_Free_Count); - } - } #endif - fs->fs_type = fmt; /* FAT sub-type */ - fs->id = ++Fsid; /* File system mount ID */ - fs->winsect = 0; /* Invalidate sector cache */ - fs->wflag = 0; + fs->fs_type = fmt; /* FAT sub-type */ + fs->id = ++Fsid; /* File system mount ID */ + fs->winsect = 0; /* Invalidate sector cache */ + fs->wflag = 0; #if _FS_RPATH - fs->cdir = 0; /* Current directory (root dir) */ + fs->cdir = 0; /* Current directory (root dir) */ #endif -#if _FS_SHARE /* Clear file lock semaphores */ - clear_lock(fs); +#if _FS_SHARE /* Clear file lock semaphores */ + clear_lock( fs ); #endif - return FR_OK; + return FR_OK; } @@ -1932,21 +2882,25 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ /*-----------------------------------------------------------------------*/ static -FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */ - FATFS *fs, /* Pointer to the file system object */ - WORD id /* Member id of the target object to be checked */ +FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */ + FATFS *fs, /* Pointer to the file system object */ + WORD id /* Member id of the target object to be checked */ ) { -// printf("fs=%p fs->fs_type=%d fs->id=%d id=%d\n", fs, fs->fs_type, fs->id, id); - if (!fs || !fs->fs_type || fs->id != id) - return FR_INVALID_OBJECT; + // printf("fs=%p fs->fs_type=%d fs->id=%d id=%d\n", fs, fs->fs_type, fs->id, id); + if ( !fs || !fs->fs_type || fs->id != id ) + { + return FR_INVALID_OBJECT; + } - ENTER_FF(fs); /* Lock file system */ + ENTER_FF( fs ); /* Lock file system */ - if (disk_status(fs->drv) & STA_NOINIT) - return FR_NOT_READY; + if ( disk_status( fs->drv ) & STA_NOINIT ) + { + return FR_NOT_READY; + } - return FR_OK; + return FR_OK; } @@ -1965,36 +2919,52 @@ FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */ /*-----------------------------------------------------------------------*/ FRESULT f_mount ( - BYTE vol, /* Logical drive number to be mounted/unmounted */ - FATFS *fs /* Pointer to new file system object (NULL for unmount)*/ + BYTE vol, /* Logical drive number to be mounted/unmounted */ + FATFS *fs /* Pointer to new file system object (NULL for unmount)*/ ) { - FATFS *rfs; + FATFS *rfs; - if (vol >= _VOLUMES) /* Check if the drive number is valid */ - return FR_INVALID_DRIVE; - rfs = FatFs[vol]; /* Get current fs object */ + if ( vol >= _VOLUMES ) /* Check if the drive number is valid */ + { + return FR_INVALID_DRIVE; + } - if (rfs) { + rfs = FatFs[vol]; /* Get current fs object */ + + if ( rfs ) + { #if _FS_SHARE - clear_lock(rfs); + clear_lock( rfs ); #endif -#if _FS_REENTRANT /* Discard sync object of the current volume */ - if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR; -#endif - rfs->fs_type = 0; /* Clear old fs object */ - } +#if _FS_REENTRANT /* Discard sync object of the current volume */ - if (fs) { - fs->fs_type = 0; /* Clear new fs object */ -#if _FS_REENTRANT /* Create sync object for the new volume */ - if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR; -#endif - } - FatFs[vol] = fs; /* Register new fs object */ + if ( !ff_del_syncobj( rfs->sobj ) ) + { + return FR_INT_ERR; + } - return FR_OK; +#endif + rfs->fs_type = 0; /* Clear old fs object */ + } + + if ( fs ) + { + fs->fs_type = 0; /* Clear new fs object */ +#if _FS_REENTRANT /* Create sync object for the new volume */ + + if ( !ff_cre_syncobj( vol, &fs->sobj ) ) + { + return FR_INT_ERR; + } + +#endif + } + + FatFs[vol] = fs; /* Register new fs object */ + + return FR_OK; } @@ -2005,125 +2975,179 @@ FRESULT f_mount ( /*-----------------------------------------------------------------------*/ FRESULT f_open ( - FIL *fp, /* Pointer to the blank file object */ - const TCHAR *path, /* Pointer to the file name */ - BYTE mode /* Access mode and file open mode flags */ + FIL *fp, /* Pointer to the blank file object */ + const TCHAR *path, /* Pointer to the file name */ + BYTE mode /* Access mode and file open mode flags */ ) { - FRESULT res; - DIR dj; - BYTE *dir; - DEF_NAMEBUF; + FRESULT res; + DIR dj; + BYTE *dir; + DEF_NAMEBUF; - fp->fs = 0; /* Clear file object */ + fp->fs = 0; /* Clear file object */ #if !_FS_READONLY - mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW; - res = chk_mounted(&path, &dj.fs, (BYTE)(mode & ~FA_READ)); + mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW; + res = chk_mounted( &path, &dj.fs, ( BYTE )( mode & ~FA_READ ) ); #else - mode &= FA_READ; - res = chk_mounted(&path, &dj.fs, 0); + mode &= FA_READ; + res = chk_mounted( &path, &dj.fs, 0 ); #endif - INIT_BUF(dj); - if (res == FR_OK) - res = follow_path(&dj, path); /* Follow the file path */ - dir = dj.dir; + INIT_BUF( dj ); + + if ( res == FR_OK ) + { + res = follow_path( &dj, path ); /* Follow the file path */ + } + + dir = dj.dir; + +#if !_FS_READONLY /* R/W configuration */ + + if ( res == FR_OK ) + { + if ( !dir ) /* Current dir itself */ + { + res = FR_INVALID_NAME; + } -#if !_FS_READONLY /* R/W configuration */ - if (res == FR_OK) { - if (!dir) /* Current dir itself */ - res = FR_INVALID_NAME; #if _FS_SHARE - else - res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); + else + { + res = chk_lock( &dj, ( mode & ~FA_READ ) ? 1 : 0 ); + } + #endif - } - /* Create or Open a file */ - if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { - DWORD dw, cl; + } - if (res != FR_OK) { /* No file, create new */ - if (res == FR_NO_FILE) /* There is no file to open, create a new entry */ + /* Create or Open a file */ + if ( mode & ( FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW ) ) + { + DWORD dw, cl; + + if ( res != FR_OK ) /* No file, create new */ + { + if ( res == FR_NO_FILE ) /* There is no file to open, create a new entry */ #if _FS_SHARE - res = enq_lock(dj.fs) ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; + res = enq_lock( dj.fs ) ? dir_register( &dj ) : FR_TOO_MANY_OPEN_FILES; + #else - res = dir_register(&dj); + res = dir_register( &dj ); #endif - mode |= FA_CREATE_ALWAYS; /* File is created */ - dir = dj.dir; /* New entry */ - } - else { /* Any object is already existing */ - if (mode & FA_CREATE_NEW) { /* Cannot create new */ - res = FR_EXIST; - } else { - if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) /* Cannot overwrite it (R/O or DIR) */ - res = FR_DENIED; - } - } - if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */ - dw = get_fattime(); /* Created time */ - ST_DWORD(dir+DIR_CrtTime, dw); - dir[DIR_Attr] = 0; /* Reset attribute */ - ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */ - cl = LD_CLUST(dir); /* Get start cluster */ - ST_CLUST(dir, 0); /* cluster = 0 */ - dj.fs->wflag = 1; - if (cl) { /* Remove the cluster chain if exist */ - dw = dj.fs->winsect; - res = remove_chain(dj.fs, cl); - if (res == FR_OK) { - dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */ - res = move_window(dj.fs, dw); - } - } - } - } - else { /* Open an existing file */ - if (res == FR_OK) { /* Follow succeeded */ - if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */ - res = FR_NO_FILE; - } else { - if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */ - res = FR_DENIED; - } - } - } - if (res == FR_OK) { - if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */ - mode |= FA__WRITTEN; - fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */ - fp->dir_ptr = dir; + mode |= FA_CREATE_ALWAYS; /* File is created */ + dir = dj.dir; /* New entry */ + } + else /* Any object is already existing */ + { + if ( mode & FA_CREATE_NEW ) /* Cannot create new */ + { + res = FR_EXIST; + } + else + { + if ( dir[DIR_Attr] & ( AM_RDO | AM_DIR ) ) /* Cannot overwrite it (R/O or DIR) */ + { + res = FR_DENIED; + } + } + } + + if ( res == FR_OK && ( mode & FA_CREATE_ALWAYS ) ) /* Truncate it if overwrite mode */ + { + dw = get_fattime(); /* Created time */ + ST_DWORD( dir + DIR_CrtTime, dw ); + dir[DIR_Attr] = 0; /* Reset attribute */ + ST_DWORD( dir + DIR_FileSize, 0 ); /* size = 0 */ + cl = LD_CLUST( dir ); /* Get start cluster */ + ST_CLUST( dir, 0 ); /* cluster = 0 */ + dj.fs->wflag = 1; + + if ( cl ) /* Remove the cluster chain if exist */ + { + dw = dj.fs->winsect; + res = remove_chain( dj.fs, cl ); + + if ( res == FR_OK ) + { + dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */ + res = move_window( dj.fs, dw ); + } + } + } + } + else /* Open an existing file */ + { + if ( res == FR_OK ) /* Follow succeeded */ + { + if ( dir[DIR_Attr] & AM_DIR ) /* It is a directory */ + { + res = FR_NO_FILE; + } + else + { + if ( ( mode & FA_WRITE ) && ( dir[DIR_Attr] & AM_RDO ) ) /* R/O violation */ + { + res = FR_DENIED; + } + } + } + } + + if ( res == FR_OK ) + { + if ( mode & FA_CREATE_ALWAYS ) /* Set file change flag if created or overwritten */ + { + mode |= FA__WRITTEN; + } + + fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */ + fp->dir_ptr = dir; #if _FS_SHARE - fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); - if (!fp->lockid) res = FR_INT_ERR; -#endif - } + fp->lockid = inc_lock( &dj, ( mode & ~FA_READ ) ? 1 : 0 ); -#else /* R/O configuration */ - if (res == FR_OK) { /* Follow succeeded */ - if (!dir) { /* Current dir itself */ - res = FR_INVALID_NAME; - } else { - if (dir[DIR_Attr] & AM_DIR) /* It is a directory */ - res = FR_NO_FILE; - } - } -#endif - FREE_BUF(); + if ( !fp->lockid ) + { + res = FR_INT_ERR; + } - if (res == FR_OK) { - fp->flag = mode; /* File access mode */ - fp->org_clust = LD_CLUST(dir); /* File start cluster */ - fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */ - fp->fptr = 0; /* File pointer */ - fp->dsect = 0; +#endif + } + +#else /* R/O configuration */ + + if ( res == FR_OK ) /* Follow succeeded */ + { + if ( !dir ) /* Current dir itself */ + { + res = FR_INVALID_NAME; + } + else + { + if ( dir[DIR_Attr] & AM_DIR ) /* It is a directory */ + { + res = FR_NO_FILE; + } + } + } + +#endif + FREE_BUF(); + + if ( res == FR_OK ) + { + fp->flag = mode; /* File access mode */ + fp->org_clust = LD_CLUST( dir ); /* File start cluster */ + fp->fsize = LD_DWORD( dir + DIR_FileSize ); /* File size */ + fp->fptr = 0; /* File pointer */ + fp->dsect = 0; #if _USE_FASTSEEK - fp->cltbl = 0; /* No cluster link map table */ + fp->cltbl = 0; /* No cluster link map table */ #endif - fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */ - } + fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */ + } - LEAVE_FF(dj.fs, res); + LEAVE_FF( dj.fs, res ); } @@ -2134,87 +3158,160 @@ FRESULT f_open ( /*-----------------------------------------------------------------------*/ FRESULT f_read ( - FIL *fp, /* Pointer to the file object */ - void *buff, /* Pointer to data buffer */ - UINT btr, /* Number of bytes to read */ - UINT *br /* Pointer to number of bytes read */ + FIL *fp, /* Pointer to the file object */ + void *buff, /* Pointer to data buffer */ + UINT btr, /* Number of bytes to read */ + UINT *br /* Pointer to number of bytes read */ ) { - FRESULT res; - DWORD clst, sect, remain; - UINT rcnt, cc; - BYTE csect, *rbuff = buff; + FRESULT res; + DWORD clst, sect, remain; + UINT rcnt, cc; + BYTE csect, *rbuff = buff; - *br = 0; /* Initialize byte counter */ + *br = 0; /* Initialize byte counter */ - res = validate(fp->fs, fp->id); /* Check validity of the object */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->flag & FA__ERROR) /* Check abort flag */ - LEAVE_FF(fp->fs, FR_INT_ERR); - if (!(fp->flag & FA_READ)) /* Check access mode */ - LEAVE_FF(fp->fs, FR_DENIED); - remain = fp->fsize - fp->fptr; - if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ + res = validate( fp->fs, fp->id ); /* Check validity of the object */ - for ( ; btr; /* Repeat until all data transferred */ - rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) { - if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ - if (!csect) { /* On the cluster boundary? */ - clst = (fp->fptr == 0) ? /* On the top of the file? */ - fp->org_clust : get_fat(fp->fs, fp->curr_clust); - if (clst <= 1) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->curr_clust = clst; /* Update current cluster */ - } - sect = clust2sect(fp->fs, fp->curr_clust); /* Get current sector */ - if (!sect) ABORT(fp->fs, FR_INT_ERR); - sect += csect; - cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */ - if (cc) { /* Read maximum contiguous sectors directly */ - if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ - cc = fp->fs->csize - csect; - if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); -#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ + if ( res != FR_OK ) + { + LEAVE_FF( fp->fs, res ); + } + + if ( fp->flag & FA__ERROR ) /* Check abort flag */ + { + LEAVE_FF( fp->fs, FR_INT_ERR ); + } + + if ( !( fp->flag & FA_READ ) ) /* Check access mode */ + { + LEAVE_FF( fp->fs, FR_DENIED ); + } + + remain = fp->fsize - fp->fptr; + + if ( btr > remain ) + { + btr = ( UINT )remain; /* Truncate btr by remaining bytes */ + } + + for ( ; btr; /* Repeat until all data transferred */ + rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt ) + { + if ( ( fp->fptr % SS( fp->fs ) ) == 0 ) /* On the sector boundary? */ + { + csect = ( BYTE )( fp->fptr / SS( fp->fs ) & ( fp->fs->csize - 1 ) ); /* Sector offset in the cluster */ + + if ( !csect ) /* On the cluster boundary? */ + { + clst = ( fp->fptr == 0 ) ? /* On the top of the file? */ + fp->org_clust : get_fat( fp->fs, fp->curr_clust ); + + if ( clst <= 1 ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + if ( clst == 0xFFFFFFFF ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->curr_clust = clst; /* Update current cluster */ + } + + sect = clust2sect( fp->fs, fp->curr_clust ); /* Get current sector */ + + if ( !sect ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + sect += csect; + cc = btr / SS( fp->fs ); /* When remaining bytes >= sector size, */ + + if ( cc ) /* Read maximum contiguous sectors directly */ + { + if ( csect + cc > fp->fs->csize ) /* Clip at cluster boundary */ + { + cc = fp->fs->csize - csect; + } + + if ( disk_read( fp->fs->drv, rbuff, sect, ( BYTE )cc ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + +#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ #if _FS_TINY - if (fp->fs->wflag && fp->fs->winsect - sect < cc) - mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs)); + + if ( fp->fs->wflag && fp->fs->winsect - sect < cc ) + { + mem_cpy( rbuff + ( ( fp->fs->winsect - sect ) * SS( fp->fs ) ), fp->fs->win, SS( fp->fs ) ); + } + #else - if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc){ - mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); } + + if ( ( fp->flag & FA__DIRTY ) && fp->dsect - sect < cc ) + { + mem_cpy( rbuff + ( ( fp->dsect - sect ) * SS( fp->fs ) ), fp->buf, SS( fp->fs ) ); + } + #endif #endif - rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ - continue; - } + rcnt = SS( fp->fs ) * cc; /* Number of bytes transferred */ + continue; + } + #if !_FS_TINY #if !_FS_READONLY - if (fp->flag & FA__DIRTY) { /* Write sector I/O buffer if needed */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } + + if ( fp->flag & FA__DIRTY ) /* Write sector I/O buffer if needed */ + { + if ( disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->flag &= ~FA__DIRTY; + } + #endif - if (fp->dsect != sect) { /* Fill sector buffer with file data */ - if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - } + + if ( fp->dsect != sect ) /* Fill sector buffer with file data */ + { + if ( disk_read( fp->fs->drv, fp->buf, sect, 1 ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + } + #endif - fp->dsect = sect; - } - rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */ - if (rcnt > btr) rcnt = btr; + fp->dsect = sect; + } + + rcnt = SS( fp->fs ) - ( fp->fptr % SS( fp->fs ) ); /* Get partial sector data from sector buffer */ + + if ( rcnt > btr ) + { + rcnt = btr; + } + #if _FS_TINY - if (move_window(fp->fs, fp->dsect)) /* Move sector window */ - ABORT(fp->fs, FR_DISK_ERR); - mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ + + if ( move_window( fp->fs, fp->dsect ) ) /* Move sector window */ + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + mem_cpy( rbuff, &fp->fs->win[fp->fptr % SS( fp->fs )], rcnt ); /* Pick partial sector */ #else - mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ + mem_cpy( rbuff, &fp->buf[fp->fptr % SS( fp->fs )], rcnt ); /* Pick partial sector */ #endif - } - LEAVE_FF(fp->fs, FR_OK); + } + + LEAVE_FF( fp->fs, FR_OK ); } @@ -2226,110 +3323,205 @@ FRESULT f_read ( /*-----------------------------------------------------------------------*/ FRESULT f_write ( - FIL *fp, /* Pointer to the file object */ - const void *buff, /* Pointer to the data to be written */ - UINT btw, /* Number of bytes to write */ - UINT *bw /* Pointer to number of bytes written */ + FIL *fp, /* Pointer to the file object */ + const void *buff, /* Pointer to the data to be written */ + UINT btw, /* Number of bytes to write */ + UINT *bw /* Pointer to number of bytes written */ ) { - FRESULT res; - DWORD clst, sect; - UINT wcnt, cc; - const BYTE *wbuff = buff; - BYTE csect; + FRESULT res; + DWORD clst, sect; + UINT wcnt, cc; + const BYTE *wbuff = buff; + BYTE csect; - *bw = 0; /* Initialize byte counter */ + *bw = 0; /* Initialize byte counter */ - res = validate(fp->fs, fp->id); /* Check validity of the object */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->flag & FA__ERROR) /* Check abort flag */ - LEAVE_FF(fp->fs, FR_INT_ERR); - if (!(fp->flag & FA_WRITE)) /* Check access mode */ - LEAVE_FF(fp->fs, FR_DENIED); - if (fp->fsize + btw < fp->fsize) btw = 0; /* File size cannot reach 4GB */ + res = validate( fp->fs, fp->id ); /* Check validity of the object */ + + if ( res != FR_OK ) + { + LEAVE_FF( fp->fs, res ); + } + + if ( fp->flag & FA__ERROR ) /* Check abort flag */ + { + LEAVE_FF( fp->fs, FR_INT_ERR ); + } + + if ( !( fp->flag & FA_WRITE ) ) /* Check access mode */ + { + LEAVE_FF( fp->fs, FR_DENIED ); + } + + if ( fp->fsize + btw < fp->fsize ) + { + btw = 0; /* File size cannot reach 4GB */ + } + + for ( ; btw; /* Repeat until all data transferred */ + wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt ) + { + if ( ( fp->fptr % SS( fp->fs ) ) == 0 ) /* On the sector boundary? */ + { + csect = ( BYTE )( fp->fptr / SS( fp->fs ) & ( fp->fs->csize - 1 ) ); /* Sector offset in the cluster */ + + if ( !csect ) /* On the cluster boundary? */ + { + if ( fp->fptr == 0 ) /* On the top of the file? */ + { + clst = fp->org_clust; /* Follow from the origin */ + + if ( clst == 0 ) /* When there is no cluster chain, */ + { + fp->org_clust = clst = create_chain( fp->fs, 0 ); /* Create a new cluster chain */ + } + } + else /* Middle or end of the file */ + { + clst = create_chain( fp->fs, fp->curr_clust ); /* Follow or stretch cluster chain */ + } + + if ( clst == 0 ) + { + break; /* Could not allocate a new cluster (disk full) */ + } + + if ( clst == 1 ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + if ( clst == 0xFFFFFFFF ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->curr_clust = clst; /* Update current cluster */ + } - for ( ; btw; /* Repeat until all data transferred */ - wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) { - if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ - if (!csect) { /* On the cluster boundary? */ - if (fp->fptr == 0) { /* On the top of the file? */ - clst = fp->org_clust; /* Follow from the origin */ - if (clst == 0) /* When there is no cluster chain, */ - fp->org_clust = clst = create_chain(fp->fs, 0); /* Create a new cluster chain */ - } else { /* Middle or end of the file */ - clst = create_chain(fp->fs, fp->curr_clust); /* Follow or stretch cluster chain */ - } - if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ - if (clst == 1) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->curr_clust = clst; /* Update current cluster */ - } #if _FS_TINY - if (fp->fs->winsect == fp->dsect && move_window(fp->fs, 0)) /* Write back data buffer prior to following direct transfer */ - ABORT(fp->fs, FR_DISK_ERR); -#else - if (fp->flag & FA__DIRTY) { /* Write back data buffer prior to following direct transfer */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } -#endif - sect = clust2sect(fp->fs, fp->curr_clust); /* Get current sector */ - if (!sect) ABORT(fp->fs, FR_INT_ERR); - sect += csect; - cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */ - if (cc) { /* Write maximum contiguous sectors directly */ - if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ - cc = fp->fs->csize - csect; - if (disk_write(fp->fs->drv, wbuff, sect, (BYTE)cc) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); -#if _FS_TINY - if (fp->fs->winsect - sect < cc) { /* Refill sector cache if it gets dirty by the direct write */ - mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs)); - fp->fs->wflag = 0; - } -#else - if (fp->dsect - sect < cc) { /* Refill sector cache if it gets dirty by the direct write */ - mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)), SS(fp->fs)); - fp->flag &= ~FA__DIRTY; - } -#endif - wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ - continue; - } -#if _FS_TINY - if (fp->fptr >= fp->fsize) { /* Avoid silly buffer filling at growing edge */ - if (move_window(fp->fs, 0)) ABORT(fp->fs, FR_DISK_ERR); - fp->fs->winsect = sect; - } -#else - if (fp->dsect != sect) { /* Fill sector buffer with file data */ - if (fp->fptr < fp->fsize && - disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - } -#endif - fp->dsect = sect; - } - wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */ - if (wcnt > btw) wcnt = btw; -#if _FS_TINY - if (move_window(fp->fs, fp->dsect)) /* Move sector window */ - ABORT(fp->fs, FR_DISK_ERR); - mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */ - fp->fs->wflag = 1; -#else - mem_cpy(&fp->buf[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */ - fp->flag |= FA__DIRTY; -#endif - } - if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; /* Update file size if needed */ - fp->flag |= FA__WRITTEN; /* Set file change flag */ + if ( fp->fs->winsect == fp->dsect + && move_window( fp->fs, 0 ) ) /* Write back data buffer prior to following direct transfer */ + { + ABORT( fp->fs, FR_DISK_ERR ); + } - LEAVE_FF(fp->fs, FR_OK); +#else + + if ( fp->flag & FA__DIRTY ) /* Write back data buffer prior to following direct transfer */ + { + if ( disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->flag &= ~FA__DIRTY; + } + +#endif + sect = clust2sect( fp->fs, fp->curr_clust ); /* Get current sector */ + + if ( !sect ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + sect += csect; + cc = btw / SS( fp->fs ); /* When remaining bytes >= sector size, */ + + if ( cc ) /* Write maximum contiguous sectors directly */ + { + if ( csect + cc > fp->fs->csize ) /* Clip at cluster boundary */ + { + cc = fp->fs->csize - csect; + } + + if ( disk_write( fp->fs->drv, wbuff, sect, ( BYTE )cc ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + +#if _FS_TINY + + if ( fp->fs->winsect - sect < cc ) /* Refill sector cache if it gets dirty by the direct write */ + { + mem_cpy( fp->fs->win, wbuff + ( ( fp->fs->winsect - sect ) * SS( fp->fs ) ), SS( fp->fs ) ); + fp->fs->wflag = 0; + } + +#else + + if ( fp->dsect - sect < cc ) /* Refill sector cache if it gets dirty by the direct write */ + { + mem_cpy( fp->buf, wbuff + ( ( fp->dsect - sect ) * SS( fp->fs ) ), SS( fp->fs ) ); + fp->flag &= ~FA__DIRTY; + } + +#endif + wcnt = SS( fp->fs ) * cc; /* Number of bytes transferred */ + continue; + } + +#if _FS_TINY + + if ( fp->fptr >= fp->fsize ) /* Avoid silly buffer filling at growing edge */ + { + if ( move_window( fp->fs, 0 ) ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->fs->winsect = sect; + } + +#else + + if ( fp->dsect != sect ) /* Fill sector buffer with file data */ + { + if ( fp->fptr < fp->fsize && + disk_read( fp->fs->drv, fp->buf, sect, 1 ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + } + +#endif + fp->dsect = sect; + } + + wcnt = SS( fp->fs ) - ( fp->fptr % SS( fp->fs ) ); /* Put partial sector into file I/O buffer */ + + if ( wcnt > btw ) + { + wcnt = btw; + } + +#if _FS_TINY + + if ( move_window( fp->fs, fp->dsect ) ) /* Move sector window */ + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + mem_cpy( &fp->fs->win[fp->fptr % SS( fp->fs )], wbuff, wcnt ); /* Fit partial sector */ + fp->fs->wflag = 1; +#else + mem_cpy( &fp->buf[fp->fptr % SS( fp->fs )], wbuff, wcnt ); /* Fit partial sector */ + fp->flag |= FA__DIRTY; +#endif + } + + if ( fp->fptr > fp->fsize ) + { + fp->fsize = fp->fptr; /* Update file size if needed */ + } + + fp->flag |= FA__WRITTEN; /* Set file change flag */ + + LEAVE_FF( fp->fs, FR_OK ); } @@ -2340,41 +3532,52 @@ FRESULT f_write ( /*-----------------------------------------------------------------------*/ FRESULT f_sync ( - FIL *fp /* Pointer to the file object */ + FIL *fp /* Pointer to the file object */ ) { - FRESULT res; - DWORD tim; - BYTE *dir; + FRESULT res; + DWORD tim; + BYTE *dir; - res = validate(fp->fs, fp->id); /* Check validity of the object */ - if (res == FR_OK) { - if (fp->flag & FA__WRITTEN) { /* Has the file been written? */ -#if !_FS_TINY /* Write-back dirty buffer */ - if (fp->flag & FA__DIRTY) { - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - LEAVE_FF(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } + res = validate( fp->fs, fp->id ); /* Check validity of the object */ + + if ( res == FR_OK ) + { + if ( fp->flag & FA__WRITTEN ) /* Has the file been written? */ + { +#if !_FS_TINY /* Write-back dirty buffer */ + + if ( fp->flag & FA__DIRTY ) + { + if ( disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK ) + { + LEAVE_FF( fp->fs, FR_DISK_ERR ); + } + + fp->flag &= ~FA__DIRTY; + } + #endif - /* Update the directory entry */ - res = move_window(fp->fs, fp->dir_sect); - if (res == FR_OK) { - dir = fp->dir_ptr; - dir[DIR_Attr] |= AM_ARC; /* Set archive bit */ - ST_DWORD(dir+DIR_FileSize, fp->fsize); /* Update file size */ - ST_CLUST(dir, fp->org_clust); /* Update start cluster */ - tim = get_fattime(); /* Update updated time */ - ST_DWORD(dir+DIR_WrtTime, tim); - fp->flag &= ~FA__WRITTEN; - fp->fs->wflag = 1; - res = sync(fp->fs); - } - } - } + /* Update the directory entry */ + res = move_window( fp->fs, fp->dir_sect ); - LEAVE_FF(fp->fs, res); + if ( res == FR_OK ) + { + dir = fp->dir_ptr; + dir[DIR_Attr] |= AM_ARC; /* Set archive bit */ + ST_DWORD( dir + DIR_FileSize, fp->fsize ); /* Update file size */ + ST_CLUST( dir, fp->org_clust ); /* Update start cluster */ + tim = get_fattime(); /* Update updated time */ + ST_DWORD( dir + DIR_WrtTime, tim ); + fp->flag &= ~FA__WRITTEN; + fp->fs->wflag = 1; + res = sync( fp->fs ); + } + } + } + + LEAVE_FF( fp->fs, res ); } #endif /* !_FS_READONLY */ @@ -2387,34 +3590,50 @@ FRESULT f_sync ( /*-----------------------------------------------------------------------*/ FRESULT f_close ( - FIL *fp /* Pointer to the file object to be closed */ + FIL *fp /* Pointer to the file object to be closed */ ) { - FRESULT res; + FRESULT res; #if _FS_READONLY - FATFS *fs = fp->fs; - res = validate(fs, fp->id); - if (res == FR_OK) fp->fs = 0; /* Discard file object */ - LEAVE_FF(fs, res); + FATFS *fs = fp->fs; + res = validate( fs, fp->id ); + + if ( res == FR_OK ) + { + fp->fs = 0; /* Discard file object */ + } + + LEAVE_FF( fs, res ); #else - res = f_sync(fp); /* Flush cached data */ + res = f_sync( fp ); /* Flush cached data */ #if _FS_SHARE - if (res == FR_OK) { /* Decrement open counter */ + + if ( res == FR_OK ) /* Decrement open counter */ + { #if _FS_REENTRANT - res = validate(fp->fs, fp->id); - if (res == FR_OK) { - res = dec_lock(fp->lockid); - unlock_fs(fp->fs, FR_OK); - } + res = validate( fp->fs, fp->id ); + + if ( res == FR_OK ) + { + res = dec_lock( fp->lockid ); + unlock_fs( fp->fs, FR_OK ); + } + #else - res = dec_lock(fp->lockid); + res = dec_lock( fp->lockid ); #endif - } + } + #endif - if (res == FR_OK) fp->fs = 0; /* Discard file object */ - return res; + + if ( res == FR_OK ) + { + fp->fs = 0; /* Discard file object */ + } + + return res; #endif } @@ -2428,117 +3647,196 @@ FRESULT f_close ( #if _FS_RPATH >= 1 FRESULT f_chdrive ( - BYTE drv /* Drive number */ + BYTE drv /* Drive number */ ) { - if (drv >= _VOLUMES) return FR_INVALID_DRIVE; + if ( drv >= _VOLUMES ) + { + return FR_INVALID_DRIVE; + } - CurrVol = drv; + CurrVol = drv; - return FR_OK; + return FR_OK; } FRESULT f_chdir ( - const TCHAR *path /* Pointer to the directory path */ + const TCHAR *path /* Pointer to the directory path */ ) { - FRESULT res; - DIR dj; - DEF_NAMEBUF; + FRESULT res; + DIR dj; + DEF_NAMEBUF; - res = chk_mounted(&path, &dj.fs, 0); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the path */ - FREE_BUF(); - if (res == FR_OK) { /* Follow completed */ - if (!dj.dir) { - dj.fs->cdir = dj.sclust; /* Start directory itself */ - } else { - if (dj.dir[DIR_Attr] & AM_DIR) /* Reached to the directory */ - dj.fs->cdir = LD_CLUST(dj.dir); - else - res = FR_NO_PATH; /* Reached but a file */ - } - } - if (res == FR_NO_FILE) res = FR_NO_PATH; - } + res = chk_mounted( &path, &dj.fs, 0 ); - LEAVE_FF(dj.fs, res); + if ( res == FR_OK ) + { + INIT_BUF( dj ); + res = follow_path( &dj, path ); /* Follow the path */ + FREE_BUF(); + + if ( res == FR_OK ) /* Follow completed */ + { + if ( !dj.dir ) + { + dj.fs->cdir = dj.sclust; /* Start directory itself */ + } + else + { + if ( dj.dir[DIR_Attr] & AM_DIR ) /* Reached to the directory */ + { + dj.fs->cdir = LD_CLUST( dj.dir ); + } + else + { + res = FR_NO_PATH; /* Reached but a file */ + } + } + } + + if ( res == FR_NO_FILE ) + { + res = FR_NO_PATH; + } + } + + LEAVE_FF( dj.fs, res ); } #if _FS_RPATH >= 2 FRESULT f_getcwd ( - TCHAR *path, /* Pointer to the directory path */ - UINT sz_path /* Size of path */ + TCHAR *path, /* Pointer to the directory path */ + UINT sz_path /* Size of path */ ) { - FRESULT res; - DIR dj; - UINT i, n; - DWORD ccl; - TCHAR *tp; - FILINFO fno; - DEF_NAMEBUF; + FRESULT res; + DIR dj; + UINT i, n; + DWORD ccl; + TCHAR *tp; + FILINFO fno; + DEF_NAMEBUF; - *path = 0; - res = chk_mounted((const TCHAR**)&path, &dj.fs, 0); /* Get current volume */ - if (res == FR_OK) { - INIT_BUF(dj); - i = sz_path; /* Bottom of buffer (dir stack base) */ - dj.sclust = dj.fs->cdir; /* Start to follow upper dir from current dir */ - while ((ccl = dj.sclust) != 0) { /* Repeat while current dir is a sub-dir */ - res = dir_sdi(&dj, 1); /* Get parent dir */ - if (res != FR_OK) break; - res = dir_read(&dj); - if (res != FR_OK) break; - dj.sclust = LD_CLUST(dj.dir); /* Goto parent dir */ - res = dir_sdi(&dj, 0); - if (res != FR_OK) break; - do { /* Find the entry links to the child dir */ - res = dir_read(&dj); - if (res != FR_OK) break; - if (ccl == LD_CLUST(dj.dir)) break; /* Found the entry */ - res = dir_next(&dj, 0); - } while (res == FR_OK); - if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ - if (res != FR_OK) break; + *path = 0; + res = chk_mounted( ( const TCHAR ** )&path, &dj.fs, 0 ); /* Get current volume */ + + if ( res == FR_OK ) + { + INIT_BUF( dj ); + i = sz_path; /* Bottom of buffer (dir stack base) */ + dj.sclust = dj.fs->cdir; /* Start to follow upper dir from current dir */ + + while ( ( ccl = dj.sclust ) != 0 ) /* Repeat while current dir is a sub-dir */ + { + res = dir_sdi( &dj, 1 ); /* Get parent dir */ + + if ( res != FR_OK ) + { + break; + } + + res = dir_read( &dj ); + + if ( res != FR_OK ) + { + break; + } + + dj.sclust = LD_CLUST( dj.dir ); /* Goto parent dir */ + res = dir_sdi( &dj, 0 ); + + if ( res != FR_OK ) + { + break; + } + + do /* Find the entry links to the child dir */ + { + res = dir_read( &dj ); + + if ( res != FR_OK ) + { + break; + } + + if ( ccl == LD_CLUST( dj.dir ) ) + { + break; /* Found the entry */ + } + + res = dir_next( &dj, 0 ); + } + while ( res == FR_OK ); + + if ( res == FR_NO_FILE ) + { + res = FR_INT_ERR; /* It cannot be 'not found'. */ + } + + if ( res != FR_OK ) + { + break; + } + #if _USE_LFN - fno.lfname = path; - fno.lfsize = i; + fno.lfname = path; + fno.lfsize = i; #endif - get_fileinfo(&dj, &fno); /* Get the dir name and push it to the buffer */ - tp = fno.fname; - if (_USE_LFN && *path) tp = path; - for (n = 0; tp[n]; n++) ; - if (i < n + 3) { - res = FR_NOT_ENOUGH_CORE; break; - } - while (n) path[--i] = tp[--n]; - path[--i] = '/'; - } - tp = path; - if (res == FR_OK) { - *tp++ = '0' + CurrVol; /* Put drive number */ - *tp++ = ':'; - if (i == sz_path) { /* Root-dir */ - *tp++ = '/'; - } else { /* Sub-dir */ - do /* Add stacked path str */ - *tp++ = path[i++]; - while (i < sz_path); - } - } - *tp = 0; - FREE_BUF(); - } + get_fileinfo( &dj, &fno ); /* Get the dir name and push it to the buffer */ + tp = fno.fname; - LEAVE_FF(dj.fs, res); + if ( _USE_LFN && *path ) + { + tp = path; + } + + for ( n = 0; tp[n]; n++ ) ; + + if ( i < n + 3 ) + { + res = FR_NOT_ENOUGH_CORE; break; + } + + while ( n ) + { + path[--i] = tp[--n]; + } + + path[--i] = '/'; + } + + tp = path; + + if ( res == FR_OK ) + { + *tp++ = '0' + CurrVol; /* Put drive number */ + *tp++ = ':'; + + if ( i == sz_path ) /* Root-dir */ + { + *tp++ = '/'; + } + else /* Sub-dir */ + { + do /* Add stacked path str */ + { + *tp++ = path[i++]; + } + while ( i < sz_path ); + } + } + + *tp = 0; + FREE_BUF(); + } + + LEAVE_FF( dj.fs, res ); } #endif /* _FS_RPATH >= 2 */ #endif /* _FS_RPATH >= 1 */ @@ -2551,159 +3849,289 @@ FRESULT f_getcwd ( /*-----------------------------------------------------------------------*/ FRESULT f_lseek ( - FIL *fp, /* Pointer to the file object */ - DWORD ofs /* File pointer from top of file */ + FIL *fp, /* Pointer to the file object */ + DWORD ofs /* File pointer from top of file */ ) { - FRESULT res; + FRESULT res; - res = validate(fp->fs, fp->id); /* Check validity of the object */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->flag & FA__ERROR) /* Check abort flag */ - LEAVE_FF(fp->fs, FR_INT_ERR); + res = validate( fp->fs, fp->id ); /* Check validity of the object */ + + if ( res != FR_OK ) + { + LEAVE_FF( fp->fs, res ); + } + + if ( fp->flag & FA__ERROR ) /* Check abort flag */ + { + LEAVE_FF( fp->fs, FR_INT_ERR ); + } #if _USE_FASTSEEK - if (fp->cltbl) { /* Fast seek */ - DWORD cl, pcl, ncl, tcl, dsc, tlen, *tbl = fp->cltbl; - BYTE csc; - tlen = *tbl++; - if (ofs == CREATE_LINKMAP) { /* Create link map table */ - cl = fp->org_clust; - if (cl) { - do { - if (tlen < 4) { /* Not enough table items */ - res = FR_NOT_ENOUGH_CORE; break; - } - tcl = cl; ncl = 0; - do { /* Get a fragment and store the top and length */ - pcl = cl; ncl++; - cl = get_fat(fp->fs, cl); - if (cl <= 1) ABORT(fp->fs, FR_INT_ERR); - if (cl == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - } while (cl == pcl + 1); - *tbl++ = ncl; *tbl++ = tcl; - tlen -= 2; - } while (cl < fp->fs->n_fatent); - } - *tbl = 0; /* Terminate table */ + if ( fp->cltbl ) /* Fast seek */ + { + DWORD cl, pcl, ncl, tcl, dsc, tlen, *tbl = fp->cltbl; + BYTE csc; - } else { /* Fast seek */ - if (ofs > fp->fsize) /* Clip offset at the file size */ - ofs = fp->fsize; - fp->fptr = ofs; /* Set file pointer */ - if (ofs) { - dsc = (ofs - 1) / SS(fp->fs); - cl = dsc / fp->fs->csize; - for (;;) { - ncl = *tbl++; - if (!ncl) ABORT(fp->fs, FR_INT_ERR); - if (cl < ncl) break; - cl -= ncl; tbl++; - } - fp->curr_clust = cl + *tbl; - csc = (BYTE)(dsc & (fp->fs->csize - 1)); - dsc = clust2sect(fp->fs, fp->curr_clust); - if (!dsc) ABORT(fp->fs, FR_INT_ERR); - dsc += csc; - if (fp->fptr % SS(fp->fs) && dsc != fp->dsect) { + tlen = *tbl++; + + if ( ofs == CREATE_LINKMAP ) /* Create link map table */ + { + cl = fp->org_clust; + + if ( cl ) + { + do + { + if ( tlen < 4 ) /* Not enough table items */ + { + res = FR_NOT_ENOUGH_CORE; break; + } + + tcl = cl; ncl = 0; + + do /* Get a fragment and store the top and length */ + { + pcl = cl; ncl++; + cl = get_fat( fp->fs, cl ); + + if ( cl <= 1 ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + if ( cl == 0xFFFFFFFF ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + } + while ( cl == pcl + 1 ); + + *tbl++ = ncl; *tbl++ = tcl; + tlen -= 2; + } + while ( cl < fp->fs->n_fatent ); + } + + *tbl = 0; /* Terminate table */ + + } + else /* Fast seek */ + { + if ( ofs > fp->fsize ) /* Clip offset at the file size */ + { + ofs = fp->fsize; + } + + fp->fptr = ofs; /* Set file pointer */ + + if ( ofs ) + { + dsc = ( ofs - 1 ) / SS( fp->fs ); + cl = dsc / fp->fs->csize; + + for ( ;; ) + { + ncl = *tbl++; + + if ( !ncl ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + if ( cl < ncl ) + { + break; + } + + cl -= ncl; tbl++; + } + + fp->curr_clust = cl + *tbl; + csc = ( BYTE )( dsc & ( fp->fs->csize - 1 ) ); + dsc = clust2sect( fp->fs, fp->curr_clust ); + + if ( !dsc ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + dsc += csc; + + if ( fp->fptr % SS( fp->fs ) && dsc != fp->dsect ) + { #if !_FS_TINY #if !_FS_READONLY - if (fp->flag & FA__DIRTY) { /* Flush dirty buffer if needed */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } -#endif - if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); -#endif - fp->dsect = dsc; - } - } - } - } else + + if ( fp->flag & FA__DIRTY ) /* Flush dirty buffer if needed */ + { + if ( disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->flag &= ~FA__DIRTY; + } + #endif - /* Normal Seek */ - { - DWORD clst, bcs, nsect, ifptr; + if ( disk_read( fp->fs->drv, fp->buf, dsc, 1 ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } - if (ofs > fp->fsize /* In read-only mode, clip offset with the file size */ -#if !_FS_READONLY - && !(fp->flag & FA_WRITE) #endif - ) ofs = fp->fsize; + fp->dsect = dsc; + } + } + } + } + else +#endif - ifptr = fp->fptr; - fp->fptr = nsect = 0; - if (ofs) { - bcs = (DWORD)fp->fs->csize * SS(fp->fs); /* Cluster size (byte) */ - if (ifptr > 0 && - (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ - fp->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */ - ofs -= fp->fptr; - clst = fp->curr_clust; - } else { /* When seek to back cluster, */ - clst = fp->org_clust; /* start from the first cluster */ + /* Normal Seek */ + { + DWORD clst, bcs, nsect, ifptr; + + if ( ofs > fp->fsize /* In read-only mode, clip offset with the file size */ #if !_FS_READONLY - if (clst == 0) { /* If no cluster chain, create a new chain */ - clst = create_chain(fp->fs, 0); - if (clst == 1) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->org_clust = clst; - } + && !( fp->flag & FA_WRITE ) #endif - fp->curr_clust = clst; - } - if (clst != 0) { - while (ofs > bcs) { /* Cluster following loop */ + ) + { + ofs = fp->fsize; + } + + ifptr = fp->fptr; + fp->fptr = nsect = 0; + + if ( ofs ) + { + bcs = ( DWORD )fp->fs->csize * SS( fp->fs ); /* Cluster size (byte) */ + + if ( ifptr > 0 && + ( ofs - 1 ) / bcs >= ( ifptr - 1 ) / bcs ) /* When seek to same or following cluster, */ + { + fp->fptr = ( ifptr - 1 ) & ~( bcs - 1 ); /* start from the current cluster */ + ofs -= fp->fptr; + clst = fp->curr_clust; + } + else /* When seek to back cluster, */ + { + clst = fp->org_clust; /* start from the first cluster */ #if !_FS_READONLY - if (fp->flag & FA_WRITE) { /* Check if in write mode or not */ - clst = create_chain(fp->fs, clst); /* Force stretch if in write mode */ - if (clst == 0) { /* When disk gets full, clip file size */ - ofs = bcs; break; - } - } else + + if ( clst == 0 ) /* If no cluster chain, create a new chain */ + { + clst = create_chain( fp->fs, 0 ); + + if ( clst == 1 ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + if ( clst == 0xFFFFFFFF ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->org_clust = clst; + } + #endif - clst = get_fat(fp->fs, clst); /* Follow cluster chain if not in write mode */ - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR); - fp->curr_clust = clst; - fp->fptr += bcs; - ofs -= bcs; - } - fp->fptr += ofs; - if (ofs % SS(fp->fs)) { - nsect = clust2sect(fp->fs, clst); /* Current sector */ - if (!nsect) ABORT(fp->fs, FR_INT_ERR); - nsect += ofs / SS(fp->fs); - } - } - } - if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) { + fp->curr_clust = clst; + } + + if ( clst != 0 ) + { + while ( ofs > bcs ) /* Cluster following loop */ + { +#if !_FS_READONLY + + if ( fp->flag & FA_WRITE ) /* Check if in write mode or not */ + { + clst = create_chain( fp->fs, clst ); /* Force stretch if in write mode */ + + if ( clst == 0 ) /* When disk gets full, clip file size */ + { + ofs = bcs; break; + } + } + else +#endif + clst = get_fat( fp->fs, clst ); /* Follow cluster chain if not in write mode */ + + if ( clst == 0xFFFFFFFF ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + if ( clst <= 1 || clst >= fp->fs->n_fatent ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + fp->curr_clust = clst; + fp->fptr += bcs; + ofs -= bcs; + } + + fp->fptr += ofs; + + if ( ofs % SS( fp->fs ) ) + { + nsect = clust2sect( fp->fs, clst ); /* Current sector */ + + if ( !nsect ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + nsect += ofs / SS( fp->fs ); + } + } + } + + if ( fp->fptr % SS( fp->fs ) && nsect != fp->dsect ) + { #if !_FS_TINY #if !_FS_READONLY - if (fp->flag & FA__DIRTY) { /* Flush dirty buffer if needed */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } + + if ( fp->flag & FA__DIRTY ) /* Flush dirty buffer if needed */ + { + if ( disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->flag &= ~FA__DIRTY; + } + #endif - if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); + + if ( disk_read( fp->fs->drv, fp->buf, nsect, 1 ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + #endif - fp->dsect = nsect; - } + fp->dsect = nsect; + } + #if !_FS_READONLY - if (fp->fptr > fp->fsize) { /* Set change flag if the file size is extended */ - fp->fsize = fp->fptr; - fp->flag |= FA__WRITTEN; - } + + if ( fp->fptr > fp->fsize ) /* Set change flag if the file size is extended */ + { + fp->fsize = fp->fptr; + fp->flag |= FA__WRITTEN; + } + #endif - } - LEAVE_FF(fp->fs, res); + } + + LEAVE_FF( fp->fs, res ); } @@ -2714,36 +4142,50 @@ FRESULT f_lseek ( /*-----------------------------------------------------------------------*/ FRESULT f_opendir ( - DIR *dj, /* Pointer to directory object to create */ - const TCHAR *path /* Pointer to the directory path */ + DIR *dj, /* Pointer to directory object to create */ + const TCHAR *path /* Pointer to the directory path */ ) { - FRESULT res; - DEF_NAMEBUF; + FRESULT res; + DEF_NAMEBUF; - res = chk_mounted(&path, &dj->fs, 0); - if (res == FR_OK) { - INIT_BUF(*dj); - res = follow_path(dj, path); /* Follow the path to the directory */ - FREE_BUF(); - if (res == FR_OK) { /* Follow completed */ - if (dj->dir) { /* It is not the root dir */ - if (dj->dir[DIR_Attr] & AM_DIR) { /* The object is a directory */ - dj->sclust = LD_CLUST(dj->dir); - } else { /* The object is not a directory */ - res = FR_NO_PATH; - } - } - if (res == FR_OK) { - dj->id = dj->fs->id; - res = dir_sdi(dj, 0); /* Rewind dir */ - } - } - if (res == FR_NO_FILE) res = FR_NO_PATH; - } + res = chk_mounted( &path, &dj->fs, 0 ); - LEAVE_FF(dj->fs, res); + if ( res == FR_OK ) + { + INIT_BUF( *dj ); + res = follow_path( dj, path ); /* Follow the path to the directory */ + FREE_BUF(); + + if ( res == FR_OK ) /* Follow completed */ + { + if ( dj->dir ) /* It is not the root dir */ + { + if ( dj->dir[DIR_Attr] & AM_DIR ) /* The object is a directory */ + { + dj->sclust = LD_CLUST( dj->dir ); + } + else /* The object is not a directory */ + { + res = FR_NO_PATH; + } + } + + if ( res == FR_OK ) + { + dj->id = dj->fs->id; + res = dir_sdi( dj, 0 ); /* Rewind dir */ + } + } + + if ( res == FR_NO_FILE ) + { + res = FR_NO_PATH; + } + } + + LEAVE_FF( dj->fs, res ); } @@ -2754,38 +4196,50 @@ FRESULT f_opendir ( /*-----------------------------------------------------------------------*/ FRESULT f_readdir ( - DIR *dj, /* Pointer to the open directory object */ - FILINFO *fno /* Pointer to file information to return */ + DIR *dj, /* Pointer to the open directory object */ + FILINFO *fno /* Pointer to file information to return */ ) { - FRESULT res; - DEF_NAMEBUF; + FRESULT res; + DEF_NAMEBUF; - res = validate(dj->fs, dj->id); /* Check validity of the object */ - if (res == FR_OK) { - if (!fno) { - res = dir_sdi(dj, 0); /* Rewind the directory object */ - } else { - INIT_BUF(*dj); - res = dir_read(dj); /* Read an directory item */ - if (res == FR_NO_FILE) { /* Reached end of dir */ - dj->sect = 0; - res = FR_OK; - } - if (res == FR_OK) { /* A valid entry is found */ - get_fileinfo(dj, fno); /* Get the object information */ - res = dir_next(dj, 0); /* Increment index for next */ - if (res == FR_NO_FILE) { - dj->sect = 0; - res = FR_OK; - } - } - FREE_BUF(); - } - } + res = validate( dj->fs, dj->id ); /* Check validity of the object */ - LEAVE_FF(dj->fs, res); + if ( res == FR_OK ) + { + if ( !fno ) + { + res = dir_sdi( dj, 0 ); /* Rewind the directory object */ + } + else + { + INIT_BUF( *dj ); + res = dir_read( dj ); /* Read an directory item */ + + if ( res == FR_NO_FILE ) /* Reached end of dir */ + { + dj->sect = 0; + res = FR_OK; + } + + if ( res == FR_OK ) /* A valid entry is found */ + { + get_fileinfo( dj, fno ); /* Get the object information */ + res = dir_next( dj, 0 ); /* Increment index for next */ + + if ( res == FR_NO_FILE ) + { + dj->sect = 0; + res = FR_OK; + } + } + + FREE_BUF(); + } + } + + LEAVE_FF( dj->fs, res ); } @@ -2796,49 +4250,58 @@ FRESULT f_readdir ( /*-----------------------------------------------------------------------*/ FRESULT f_stat ( - const TCHAR *path, /* Pointer to the file path */ - FILINFO *fno /* Pointer to file information to return */ + const TCHAR *path, /* Pointer to the file path */ + FILINFO *fno /* Pointer to file information to return */ ) { - FRESULT res; - DIR dj; - DEF_NAMEBUF; + FRESULT res; + DIR dj; + DEF_NAMEBUF; - res = chk_mounted(&path, &dj.fs, 0); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - if (res == FR_OK) { /* Follow completed */ - if (dj.dir) /* Found an object */ - get_fileinfo(&dj, fno); - else /* It is root dir */ - res = FR_INVALID_NAME; - } - FREE_BUF(); - } + res = chk_mounted( &path, &dj.fs, 0 ); - LEAVE_FF(dj.fs, res); + if ( res == FR_OK ) + { + INIT_BUF( dj ); + res = follow_path( &dj, path ); /* Follow the file path */ + + if ( res == FR_OK ) /* Follow completed */ + { + if ( dj.dir ) /* Found an object */ + { + get_fileinfo( &dj, fno ); + } + else /* It is root dir */ + { + res = FR_INVALID_NAME; + } + } + + FREE_BUF(); + } + + LEAVE_FF( dj.fs, res ); } FRESULT l_openfilebycluster ( - FATFS *fs, /* Pointer to file system object */ - FIL *fp, /* Pointer to the blank file object */ - const TCHAR *path, - DWORD clust, /* Cluster number to be opened */ - DWORD fsize /* File size to be assumed */ + FATFS *fs, /* Pointer to file system object */ + FIL *fp, /* Pointer to the blank file object */ + const TCHAR *path, + DWORD clust, /* Cluster number to be opened */ + DWORD fsize /* File size to be assumed */ ) { - chk_mounted(&path, &fs, 0); - fp->flag = FA_READ; - fp->org_clust = clust; - fp->fsize = fsize; - fp->fptr = 0; - fp->dsect = 0; - fp->fs = fs; + chk_mounted( &path, &fs, 0 ); + fp->flag = FA_READ; + fp->org_clust = clust; + fp->fsize = fsize; + fp->fptr = 0; + fp->dsect = 0; + fp->fs = fs; - return FR_OK; + return FR_OK; } @@ -2848,61 +4311,115 @@ FRESULT l_openfilebycluster ( /*-----------------------------------------------------------------------*/ FRESULT f_getfree ( - const TCHAR *path, /* Pointer to the logical drive number (root dir) */ - DWORD *nclst, /* Pointer to the variable to return number of free clusters */ - FATFS **fatfs /* Pointer to pointer to corresponding file system object to return */ + const TCHAR *path, /* Pointer to the logical drive number (root dir) */ + DWORD *nclst, /* Pointer to the variable to return number of free clusters */ + FATFS **fatfs /* Pointer to pointer to corresponding file system object to return */ ) { - FRESULT res; - DWORD n, clst, sect, stat; - UINT i; - BYTE fat, *p; + FRESULT res; + DWORD n, clst, sect, stat; + UINT i; + BYTE fat, *p; - /* Get drive number */ - res = chk_mounted(&path, fatfs, 0); - if (res == FR_OK) { - /* If free_clust is valid, return it without full cluster scan */ - if ((*fatfs)->free_clust <= (*fatfs)->n_fatent - 2) { - *nclst = (*fatfs)->free_clust; - } else { - /* Get number of free clusters */ - fat = (*fatfs)->fs_type; - n = 0; - if (fat == FS_FAT12) { - clst = 2; - do { - stat = get_fat(*fatfs, clst); - if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } - if (stat == 1) { res = FR_INT_ERR; break; } - if (stat == 0) n++; - } while (++clst < (*fatfs)->n_fatent); - } else { - clst = (*fatfs)->n_fatent; - sect = (*fatfs)->fatbase; - i = 0; p = 0; - do { - if (!i) { - res = move_window(*fatfs, sect++); - if (res != FR_OK) break; - p = (*fatfs)->win; - i = SS(*fatfs); - } - if (fat == FS_FAT16) { - if (LD_WORD(p) == 0) n++; - p += 2; i -= 2; - } else { - if ((LD_DWORD(p) & 0x0FFFFFFF) == 0) n++; - p += 4; i -= 4; - } - } while (--clst); - } - (*fatfs)->free_clust = n; - if (fat == FS_FAT32) (*fatfs)->fsi_flag = 1; - *nclst = n; - } - } - LEAVE_FF(*fatfs, res); + /* Get drive number */ + res = chk_mounted( &path, fatfs, 0 ); + + if ( res == FR_OK ) + { + /* If free_clust is valid, return it without full cluster scan */ + if ( ( *fatfs )->free_clust <= ( *fatfs )->n_fatent - 2 ) + { + *nclst = ( *fatfs )->free_clust; + } + else + { + /* Get number of free clusters */ + fat = ( *fatfs )->fs_type; + n = 0; + + if ( fat == FS_FAT12 ) + { + clst = 2; + + do + { + stat = get_fat( *fatfs, clst ); + + if ( stat == 0xFFFFFFFF ) + { + res = FR_DISK_ERR; + break; + } + + if ( stat == 1 ) + { + res = FR_INT_ERR; + break; + } + + if ( stat == 0 ) + { + n++; + } + } + while ( ++clst < ( *fatfs )->n_fatent ); + } + else + { + clst = ( *fatfs )->n_fatent; + sect = ( *fatfs )->fatbase; + i = 0; p = 0; + + do + { + if ( !i ) + { + res = move_window( *fatfs, sect++ ); + + if ( res != FR_OK ) + { + break; + } + + p = ( *fatfs )->win; + i = SS( *fatfs ); + } + + if ( fat == FS_FAT16 ) + { + if ( LD_WORD( p ) == 0 ) + { + n++; + } + + p += 2; i -= 2; + } + else + { + if ( ( LD_DWORD( p ) & 0x0FFFFFFF ) == 0 ) + { + n++; + } + + p += 4; i -= 4; + } + } + while ( --clst ); + } + + ( *fatfs )->free_clust = n; + + if ( fat == FS_FAT32 ) + { + ( *fatfs )->fsi_flag = 1; + } + + *nclst = n; + } + } + + LEAVE_FF( *fatfs, res ); } @@ -2913,44 +4430,76 @@ FRESULT f_getfree ( /*-----------------------------------------------------------------------*/ FRESULT f_truncate ( - FIL *fp /* Pointer to the file object */ + FIL *fp /* Pointer to the file object */ ) { - FRESULT res; - DWORD ncl; + FRESULT res; + DWORD ncl; - res = validate(fp->fs, fp->id); /* Check validity of the object */ - if (res == FR_OK) { - if (fp->flag & FA__ERROR) { /* Check abort flag */ - res = FR_INT_ERR; - } else { - if (!(fp->flag & FA_WRITE)) /* Check access mode */ - res = FR_DENIED; - } - } - if (res == FR_OK) { - if (fp->fsize > fp->fptr) { - fp->fsize = fp->fptr; /* Set file size to current R/W point */ - fp->flag |= FA__WRITTEN; - if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */ - res = remove_chain(fp->fs, fp->org_clust); - fp->org_clust = 0; - } else { /* When truncate a part of the file, remove remaining clusters */ - ncl = get_fat(fp->fs, fp->curr_clust); - res = FR_OK; - if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; - if (ncl == 1) res = FR_INT_ERR; - if (res == FR_OK && ncl < fp->fs->n_fatent) { - res = put_fat(fp->fs, fp->curr_clust, 0x0FFFFFFF); - if (res == FR_OK) res = remove_chain(fp->fs, ncl); - } - } - } - if (res != FR_OK) fp->flag |= FA__ERROR; - } + res = validate( fp->fs, fp->id ); /* Check validity of the object */ - LEAVE_FF(fp->fs, res); + if ( res == FR_OK ) + { + if ( fp->flag & FA__ERROR ) /* Check abort flag */ + { + res = FR_INT_ERR; + } + else + { + if ( !( fp->flag & FA_WRITE ) ) /* Check access mode */ + { + res = FR_DENIED; + } + } + } + + if ( res == FR_OK ) + { + if ( fp->fsize > fp->fptr ) + { + fp->fsize = fp->fptr; /* Set file size to current R/W point */ + fp->flag |= FA__WRITTEN; + + if ( fp->fptr == 0 ) /* When set file size to zero, remove entire cluster chain */ + { + res = remove_chain( fp->fs, fp->org_clust ); + fp->org_clust = 0; + } + else /* When truncate a part of the file, remove remaining clusters */ + { + ncl = get_fat( fp->fs, fp->curr_clust ); + res = FR_OK; + + if ( ncl == 0xFFFFFFFF ) + { + res = FR_DISK_ERR; + } + + if ( ncl == 1 ) + { + res = FR_INT_ERR; + } + + if ( res == FR_OK && ncl < fp->fs->n_fatent ) + { + res = put_fat( fp->fs, fp->curr_clust, 0x0FFFFFFF ); + + if ( res == FR_OK ) + { + res = remove_chain( fp->fs, ncl ); + } + } + } + } + + if ( res != FR_OK ) + { + fp->flag |= FA__ERROR; + } + } + + LEAVE_FF( fp->fs, res ); } @@ -2961,64 +4510,111 @@ FRESULT f_truncate ( /*-----------------------------------------------------------------------*/ FRESULT f_unlink ( - const TCHAR *path /* Pointer to the file or directory path */ + const TCHAR *path /* Pointer to the file or directory path */ ) { - FRESULT res; - DIR dj, sdj; - BYTE *dir; - DWORD dclst; - DEF_NAMEBUF; + FRESULT res; + DIR dj, sdj; + BYTE *dir; + DWORD dclst; + DEF_NAMEBUF; - res = chk_mounted(&path, &dj.fs, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; /* Cannot remove dot entry */ + res = chk_mounted( &path, &dj.fs, 1 ); + + if ( res == FR_OK ) + { + INIT_BUF( dj ); + res = follow_path( &dj, path ); /* Follow the file path */ + + if ( _FS_RPATH && res == FR_OK && ( dj.fn[NS] & NS_DOT ) ) + { + res = FR_INVALID_NAME; /* Cannot remove dot entry */ + } + #if _FS_SHARE - if (res == FR_OK) res = chk_lock(&dj, 2); /* Cannot remove open file */ + + if ( res == FR_OK ) + { + res = chk_lock( &dj, 2 ); /* Cannot remove open file */ + } + #endif - if (res == FR_OK) { /* The object is accessible */ - dir = dj.dir; - if (!dir) { - res = FR_INVALID_NAME; /* Cannot remove the start directory */ - } else { - if (dir[DIR_Attr] & AM_RDO) - res = FR_DENIED; /* Cannot remove R/O object */ - } - dclst = LD_CLUST(dir); - if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-dir? */ - if (dclst < 2) { - res = FR_INT_ERR; - } else { - mem_cpy(&sdj, &dj, sizeof(DIR)); /* Check if the sub-dir is empty or not */ - sdj.sclust = dclst; - res = dir_sdi(&sdj, 2); /* Exclude dot entries */ - if (res == FR_OK) { - res = dir_read(&sdj); - if (res == FR_OK /* Not empty dir */ + + if ( res == FR_OK ) /* The object is accessible */ + { + dir = dj.dir; + + if ( !dir ) + { + res = FR_INVALID_NAME; /* Cannot remove the start directory */ + } + else + { + if ( dir[DIR_Attr] & AM_RDO ) + { + res = FR_DENIED; /* Cannot remove R/O object */ + } + } + + dclst = LD_CLUST( dir ); + + if ( res == FR_OK && ( dir[DIR_Attr] & AM_DIR ) ) /* Is it a sub-dir? */ + { + if ( dclst < 2 ) + { + res = FR_INT_ERR; + } + else + { + mem_cpy( &sdj, &dj, sizeof( DIR ) ); /* Check if the sub-dir is empty or not */ + sdj.sclust = dclst; + res = dir_sdi( &sdj, 2 ); /* Exclude dot entries */ + + if ( res == FR_OK ) + { + res = dir_read( &sdj ); + + if ( res == FR_OK /* Not empty dir */ #if _FS_RPATH - || dclst == sdj.fs->cdir /* Current dir */ + || dclst == sdj.fs->cdir /* Current dir */ #endif - ) res = FR_DENIED; - if (res == FR_NO_FILE) res = FR_OK; /* Empty */ - } - } - } - if (res == FR_OK) { - res = dir_remove(&dj); /* Remove the directory entry */ - if (res == FR_OK) { - if (dclst) /* Remove the cluster chain if exist */ - res = remove_chain(dj.fs, dclst); - if (res == FR_OK) res = sync(dj.fs); - } - } - } - FREE_BUF(); - } - LEAVE_FF(dj.fs, res); + ) + { + res = FR_DENIED; + } + + if ( res == FR_NO_FILE ) + { + res = FR_OK; /* Empty */ + } + } + } + } + + if ( res == FR_OK ) + { + res = dir_remove( &dj ); /* Remove the directory entry */ + + if ( res == FR_OK ) + { + if ( dclst ) /* Remove the cluster chain if exist */ + { + res = remove_chain( dj.fs, dclst ); + } + + if ( res == FR_OK ) + { + res = sync( dj.fs ); + } + } + } + } + + FREE_BUF(); + } + + LEAVE_FF( dj.fs, res ); } @@ -3029,69 +4625,117 @@ FRESULT f_unlink ( /*-----------------------------------------------------------------------*/ FRESULT f_mkdir ( - const TCHAR *path /* Pointer to the directory path */ + const TCHAR *path /* Pointer to the directory path */ ) { - FRESULT res; - DIR dj; - BYTE *dir, n; - DWORD dsc, dcl, pcl, tim = get_fattime(); - DEF_NAMEBUF; + FRESULT res; + DIR dj; + BYTE *dir, n; + DWORD dsc, dcl, pcl, tim = get_fattime(); + DEF_NAMEBUF; - res = chk_mounted(&path, &dj.fs, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */ - if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; - if (res == FR_NO_FILE) { /* Can create a new directory */ - dcl = create_chain(dj.fs, 0); /* Allocate a cluster for the new directory table */ - res = FR_OK; - if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */ - if (dcl == 1) res = FR_INT_ERR; - if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; - if (res == FR_OK) /* Flush FAT */ - res = move_window(dj.fs, 0); - if (res == FR_OK) { /* Initialize the new directory table */ - dsc = clust2sect(dj.fs, dcl); - dir = dj.fs->win; - mem_set(dir, 0, SS(dj.fs)); - mem_set(dir+DIR_Name, ' ', 8+3); /* Create "." entry */ - dir[DIR_Name] = '.'; - dir[DIR_Attr] = AM_DIR; - ST_DWORD(dir+DIR_WrtTime, tim); - ST_CLUST(dir, dcl); - mem_cpy(dir+32, dir, 32); /* Create ".." entry */ - dir[33] = '.'; pcl = dj.sclust; - if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase) - pcl = 0; - ST_CLUST(dir+32, pcl); - for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */ - dj.fs->winsect = dsc++; - dj.fs->wflag = 1; - res = move_window(dj.fs, 0); - if (res != FR_OK) break; - mem_set(dir, 0, SS(dj.fs)); - } - } - if (res == FR_OK) res = dir_register(&dj); /* Register the object to the directoy */ - if (res != FR_OK) { - remove_chain(dj.fs, dcl); /* Could not register, remove cluster chain */ - } else { - dir = dj.dir; - dir[DIR_Attr] = AM_DIR; /* Attribute */ - ST_DWORD(dir+DIR_WrtTime, tim); /* Created time */ - ST_CLUST(dir, dcl); /* Table start cluster */ - dj.fs->wflag = 1; - res = sync(dj.fs); - } - } - FREE_BUF(); - } + res = chk_mounted( &path, &dj.fs, 1 ); - LEAVE_FF(dj.fs, res); + if ( res == FR_OK ) + { + INIT_BUF( dj ); + res = follow_path( &dj, path ); /* Follow the file path */ + + if ( res == FR_OK ) + { + res = FR_EXIST; /* Any object with same name is already existing */ + } + + if ( _FS_RPATH && res == FR_NO_FILE && ( dj.fn[NS] & NS_DOT ) ) + { + res = FR_INVALID_NAME; + } + + if ( res == FR_NO_FILE ) /* Can create a new directory */ + { + dcl = create_chain( dj.fs, 0 ); /* Allocate a cluster for the new directory table */ + res = FR_OK; + + if ( dcl == 0 ) + { + res = FR_DENIED; /* No space to allocate a new cluster */ + } + + if ( dcl == 1 ) + { + res = FR_INT_ERR; + } + + if ( dcl == 0xFFFFFFFF ) + { + res = FR_DISK_ERR; + } + + if ( res == FR_OK ) /* Flush FAT */ + { + res = move_window( dj.fs, 0 ); + } + + if ( res == FR_OK ) /* Initialize the new directory table */ + { + dsc = clust2sect( dj.fs, dcl ); + dir = dj.fs->win; + mem_set( dir, 0, SS( dj.fs ) ); + mem_set( dir + DIR_Name, ' ', 8 + 3 ); /* Create "." entry */ + dir[DIR_Name] = '.'; + dir[DIR_Attr] = AM_DIR; + ST_DWORD( dir + DIR_WrtTime, tim ); + ST_CLUST( dir, dcl ); + mem_cpy( dir + 32, dir, 32 ); /* Create ".." entry */ + dir[33] = '.'; pcl = dj.sclust; + + if ( dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase ) + { + pcl = 0; + } + + ST_CLUST( dir + 32, pcl ); + + for ( n = dj.fs->csize; n; n-- ) /* Write dot entries and clear following sectors */ + { + dj.fs->winsect = dsc++; + dj.fs->wflag = 1; + res = move_window( dj.fs, 0 ); + + if ( res != FR_OK ) + { + break; + } + + mem_set( dir, 0, SS( dj.fs ) ); + } + } + + if ( res == FR_OK ) + { + res = dir_register( &dj ); /* Register the object to the directoy */ + } + + if ( res != FR_OK ) + { + remove_chain( dj.fs, dcl ); /* Could not register, remove cluster chain */ + } + else + { + dir = dj.dir; + dir[DIR_Attr] = AM_DIR; /* Attribute */ + ST_DWORD( dir + DIR_WrtTime, tim ); /* Created time */ + ST_CLUST( dir, dcl ); /* Table start cluster */ + dj.fs->wflag = 1; + res = sync( dj.fs ); + } + } + + FREE_BUF(); + } + + LEAVE_FF( dj.fs, res ); } @@ -3102,38 +4746,49 @@ FRESULT f_mkdir ( /*-----------------------------------------------------------------------*/ FRESULT f_chmod ( - const TCHAR *path, /* Pointer to the file path */ - BYTE value, /* Attribute bits */ - BYTE mask /* Attribute mask to change */ + const TCHAR *path, /* Pointer to the file path */ + BYTE value, /* Attribute bits */ + BYTE mask /* Attribute mask to change */ ) { - FRESULT res; - DIR dj; - BYTE *dir; - DEF_NAMEBUF; + FRESULT res; + DIR dj; + BYTE *dir; + DEF_NAMEBUF; - res = chk_mounted(&path, &dj.fs, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - FREE_BUF(); - if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; - if (res == FR_OK) { - dir = dj.dir; - if (!dir) { /* Is it a root directory? */ - res = FR_INVALID_NAME; - } else { /* File or sub directory */ - mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */ - dir[DIR_Attr] = (value & mask) | (dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */ - dj.fs->wflag = 1; - res = sync(dj.fs); - } - } - } + res = chk_mounted( &path, &dj.fs, 1 ); - LEAVE_FF(dj.fs, res); + if ( res == FR_OK ) + { + INIT_BUF( dj ); + res = follow_path( &dj, path ); /* Follow the file path */ + FREE_BUF(); + + if ( _FS_RPATH && res == FR_OK && ( dj.fn[NS] & NS_DOT ) ) + { + res = FR_INVALID_NAME; + } + + if ( res == FR_OK ) + { + dir = dj.dir; + + if ( !dir ) /* Is it a root directory? */ + { + res = FR_INVALID_NAME; + } + else /* File or sub directory */ + { + mask &= AM_RDO | AM_HID | AM_SYS | AM_ARC; /* Valid attribute mask */ + dir[DIR_Attr] = ( value & mask ) | ( dir[DIR_Attr] & ( BYTE )~mask ); /* Apply attribute change */ + dj.fs->wflag = 1; + res = sync( dj.fs ); + } + } + } + + LEAVE_FF( dj.fs, res ); } @@ -3144,37 +4799,48 @@ FRESULT f_chmod ( /*-----------------------------------------------------------------------*/ FRESULT f_utime ( - const TCHAR *path, /* Pointer to the file/directory name */ - const FILINFO *fno /* Pointer to the time stamp to be set */ + const TCHAR *path, /* Pointer to the file/directory name */ + const FILINFO *fno /* Pointer to the time stamp to be set */ ) { - FRESULT res; - DIR dj; - BYTE *dir; - DEF_NAMEBUF; + FRESULT res; + DIR dj; + BYTE *dir; + DEF_NAMEBUF; - res = chk_mounted(&path, &dj.fs, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - FREE_BUF(); - if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; - if (res == FR_OK) { - dir = dj.dir; - if (!dir) { /* Root directory */ - res = FR_INVALID_NAME; - } else { /* File or sub-directory */ - ST_WORD(dir+DIR_WrtTime, fno->ftime); - ST_WORD(dir+DIR_WrtDate, fno->fdate); - dj.fs->wflag = 1; - res = sync(dj.fs); - } - } - } + res = chk_mounted( &path, &dj.fs, 1 ); - LEAVE_FF(dj.fs, res); + if ( res == FR_OK ) + { + INIT_BUF( dj ); + res = follow_path( &dj, path ); /* Follow the file path */ + FREE_BUF(); + + if ( _FS_RPATH && res == FR_OK && ( dj.fn[NS] & NS_DOT ) ) + { + res = FR_INVALID_NAME; + } + + if ( res == FR_OK ) + { + dir = dj.dir; + + if ( !dir ) /* Root directory */ + { + res = FR_INVALID_NAME; + } + else /* File or sub-directory */ + { + ST_WORD( dir + DIR_WrtTime, fno->ftime ); + ST_WORD( dir + DIR_WrtDate, fno->fdate ); + dj.fs->wflag = 1; + res = sync( dj.fs ); + } + } + } + + LEAVE_FF( dj.fs, res ); } @@ -3185,70 +4851,110 @@ FRESULT f_utime ( /*-----------------------------------------------------------------------*/ FRESULT f_rename ( - const TCHAR *path_old, /* Pointer to the old name */ - const TCHAR *path_new /* Pointer to the new name */ + const TCHAR *path_old, /* Pointer to the old name */ + const TCHAR *path_new /* Pointer to the new name */ ) { - FRESULT res; - DIR djo, djn; - BYTE buf[21], *dir; - DWORD dw; - DEF_NAMEBUF; + FRESULT res; + DIR djo, djn; + BYTE buf[21], *dir; + DWORD dw; + DEF_NAMEBUF; - res = chk_mounted(&path_old, &djo.fs, 1); - if (res == FR_OK) { - djn.fs = djo.fs; - INIT_BUF(djo); - res = follow_path(&djo, path_old); /* Check old object */ - if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; + res = chk_mounted( &path_old, &djo.fs, 1 ); + + if ( res == FR_OK ) + { + djn.fs = djo.fs; + INIT_BUF( djo ); + res = follow_path( &djo, path_old ); /* Check old object */ + + if ( _FS_RPATH && res == FR_OK && ( djo.fn[NS] & NS_DOT ) ) + { + res = FR_INVALID_NAME; + } + #if _FS_SHARE - if (res == FR_OK) res = chk_lock(&djo, 2); + + if ( res == FR_OK ) + { + res = chk_lock( &djo, 2 ); + } + #endif - if (res == FR_OK) { /* Old object is found */ - if (!djo.dir) { /* Is root dir? */ - res = FR_NO_FILE; - } else { - mem_cpy(buf, djo.dir+DIR_Attr, 21); /* Save the object information except for name */ - mem_cpy(&djn, &djo, sizeof(DIR)); /* Check new object */ - res = follow_path(&djn, path_new); - if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */ - if (res == FR_NO_FILE) { /* Is it a valid path and no name collision? */ -/* Start critical section that any interruption or error can cause cross-link */ - res = dir_register(&djn); /* Register the new entry */ - if (res == FR_OK) { - dir = djn.dir; /* Copy object information except for name */ - mem_cpy(dir+13, buf+2, 19); - dir[DIR_Attr] = buf[0] | AM_ARC; - djo.fs->wflag = 1; - if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) { /* Update .. entry in the directory if needed */ - dw = clust2sect(djn.fs, LD_CLUST(dir)); - if (!dw) { - res = FR_INT_ERR; - } else { - res = move_window(djn.fs, dw); - dir = djn.fs->win+32; /* .. entry */ - if (res == FR_OK && dir[1] == '.') { - dw = (djn.fs->fs_type == FS_FAT32 && djn.sclust == djn.fs->dirbase) ? 0 : djn.sclust; - ST_CLUST(dir, dw); - djn.fs->wflag = 1; - } - } - } - if (res == FR_OK) { - res = dir_remove(&djo); /* Remove old entry */ - if (res == FR_OK) - res = sync(djo.fs); - } - } -/* End critical section */ - } - } - } - FREE_BUF(); - } - LEAVE_FF(djo.fs, res); + + if ( res == FR_OK ) /* Old object is found */ + { + if ( !djo.dir ) /* Is root dir? */ + { + res = FR_NO_FILE; + } + else + { + mem_cpy( buf, djo.dir + DIR_Attr, 21 ); /* Save the object information except for name */ + mem_cpy( &djn, &djo, sizeof( DIR ) ); /* Check new object */ + res = follow_path( &djn, path_new ); + + if ( res == FR_OK ) + { + res = FR_EXIST; /* The new object name is already existing */ + } + + if ( res == FR_NO_FILE ) /* Is it a valid path and no name collision? */ + { + /* Start critical section that any interruption or error can cause cross-link */ + res = dir_register( &djn ); /* Register the new entry */ + + if ( res == FR_OK ) + { + dir = djn.dir; /* Copy object information except for name */ + mem_cpy( dir + 13, buf + 2, 19 ); + dir[DIR_Attr] = buf[0] | AM_ARC; + djo.fs->wflag = 1; + + if ( djo.sclust != djn.sclust && ( dir[DIR_Attr] & AM_DIR ) ) /* Update .. entry in the directory if needed */ + { + dw = clust2sect( djn.fs, LD_CLUST( dir ) ); + + if ( !dw ) + { + res = FR_INT_ERR; + } + else + { + res = move_window( djn.fs, dw ); + dir = djn.fs->win + 32; /* .. entry */ + + if ( res == FR_OK && dir[1] == '.' ) + { + dw = ( djn.fs->fs_type == FS_FAT32 && djn.sclust == djn.fs->dirbase ) ? 0 : djn.sclust; + ST_CLUST( dir, dw ); + djn.fs->wflag = 1; + } + } + } + + if ( res == FR_OK ) + { + res = dir_remove( &djo ); /* Remove old entry */ + + if ( res == FR_OK ) + { + res = sync( djo.fs ); + } + } + } + + /* End critical section */ + } + } + } + + FREE_BUF(); + } + + LEAVE_FF( djo.fs, res ); } #endif /* !_FS_READONLY */ @@ -3264,55 +4970,101 @@ FRESULT f_rename ( #if _USE_FORWARD && _FS_TINY FRESULT f_forward ( - FIL *fp, /* Pointer to the file object */ - UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */ - UINT btr, /* Number of bytes to forward */ - UINT *bf /* Pointer to number of bytes forwarded */ + FIL *fp, /* Pointer to the file object */ + UINT ( *func )( const BYTE *, UINT ), /* Pointer to the streaming function */ + UINT btr, /* Number of bytes to forward */ + UINT *bf /* Pointer to number of bytes forwarded */ ) { - FRESULT res; - DWORD remain, clst, sect; - UINT rcnt; - BYTE csect; + FRESULT res; + DWORD remain, clst, sect; + UINT rcnt; + BYTE csect; - *bf = 0; /* Initialize byte counter */ + *bf = 0; /* Initialize byte counter */ - res = validate(fp->fs, fp->id); /* Check validity of the object */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->flag & FA__ERROR) /* Check error flag */ - LEAVE_FF(fp->fs, FR_INT_ERR); - if (!(fp->flag & FA_READ)) /* Check access mode */ - LEAVE_FF(fp->fs, FR_DENIED); + res = validate( fp->fs, fp->id ); /* Check validity of the object */ - remain = fp->fsize - fp->fptr; - if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ + if ( res != FR_OK ) + { + LEAVE_FF( fp->fs, res ); + } - for ( ; btr && (*func)(0, 0); /* Repeat until all data transferred or stream becomes busy */ - fp->fptr += rcnt, *bf += rcnt, btr -= rcnt) { - csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ - if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - if (!csect) { /* On the cluster boundary? */ - clst = (fp->fptr == 0) ? /* On the top of the file? */ - fp->org_clust : get_fat(fp->fs, fp->curr_clust); - if (clst <= 1) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->curr_clust = clst; /* Update current cluster */ - } - } - sect = clust2sect(fp->fs, fp->curr_clust); /* Get current data sector */ - if (!sect) ABORT(fp->fs, FR_INT_ERR); - sect += csect; - if (move_window(fp->fs, sect)) /* Move sector window */ - ABORT(fp->fs, FR_DISK_ERR); - fp->dsect = sect; - rcnt = SS(fp->fs) - (WORD)(fp->fptr % SS(fp->fs)); /* Forward data from sector window */ - if (rcnt > btr) rcnt = btr; - rcnt = (*func)(&fp->fs->win[(WORD)fp->fptr % SS(fp->fs)], rcnt); - if (!rcnt) ABORT(fp->fs, FR_INT_ERR); - } + if ( fp->flag & FA__ERROR ) /* Check error flag */ + { + LEAVE_FF( fp->fs, FR_INT_ERR ); + } - LEAVE_FF(fp->fs, FR_OK); + if ( !( fp->flag & FA_READ ) ) /* Check access mode */ + { + LEAVE_FF( fp->fs, FR_DENIED ); + } + + remain = fp->fsize - fp->fptr; + + if ( btr > remain ) + { + btr = ( UINT )remain; /* Truncate btr by remaining bytes */ + } + + for ( ; btr && ( *func )( 0, 0 ); /* Repeat until all data transferred or stream becomes busy */ + fp->fptr += rcnt, *bf += rcnt, btr -= rcnt ) + { + csect = ( BYTE )( fp->fptr / SS( fp->fs ) & ( fp->fs->csize - 1 ) ); /* Sector offset in the cluster */ + + if ( ( fp->fptr % SS( fp->fs ) ) == 0 ) /* On the sector boundary? */ + { + if ( !csect ) /* On the cluster boundary? */ + { + clst = ( fp->fptr == 0 ) ? /* On the top of the file? */ + fp->org_clust : get_fat( fp->fs, fp->curr_clust ); + + if ( clst <= 1 ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + if ( clst == 0xFFFFFFFF ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->curr_clust = clst; /* Update current cluster */ + } + } + + sect = clust2sect( fp->fs, fp->curr_clust ); /* Get current data sector */ + + if ( !sect ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + sect += csect; + + if ( move_window( fp->fs, sect ) ) /* Move sector window */ + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->dsect = sect; + rcnt = SS( fp->fs ) - ( WORD )( fp->fptr % SS( fp->fs ) ); /* Forward data from sector window */ + + if ( rcnt > btr ) + { + rcnt = btr; + } + + rcnt = ( *func )( &fp->fs->win[( WORD )fp->fptr % SS( fp->fs )], rcnt ); + + if ( !rcnt ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + } + + LEAVE_FF( fp->fs, FR_OK ); } #endif /* _USE_FORWARD */ @@ -3322,218 +5074,342 @@ FRESULT f_forward ( /*-----------------------------------------------------------------------*/ /* Create File System on the Drive */ /*-----------------------------------------------------------------------*/ -#define N_ROOTDIR 512 /* Multiple of 32 */ -#define N_FATS 1 /* 1 or 2 */ +#define N_ROOTDIR 512 /* Multiple of 32 */ +#define N_FATS 1 /* 1 or 2 */ FRESULT f_mkfs ( - BYTE drv, /* Logical drive number */ - BYTE sfd, /* Partitioning rule 0:FDISK, 1:SFD */ - UINT au /* Allocation unit size [bytes] */ + BYTE drv, /* Logical drive number */ + BYTE sfd, /* Partitioning rule 0:FDISK, 1:SFD */ + UINT au /* Allocation unit size [bytes] */ ) { - static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0}; - static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512}; - BYTE fmt, md, *tbl; - DWORD n_clst, vs, n, wsect; - UINT i; - DWORD b_vol, b_fat, b_dir, b_data; /* Offset (LBA) */ - DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */ - FATFS *fs; - DSTATUS stat; + static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0}; + static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512}; + BYTE fmt, md, *tbl; + DWORD n_clst, vs, n, wsect; + UINT i; + DWORD b_vol, b_fat, b_dir, b_data; /* Offset (LBA) */ + DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */ + FATFS *fs; + DSTATUS stat; - /* Check mounted drive and clear work area */ - if (drv >= _VOLUMES) return FR_INVALID_DRIVE; - fs = FatFs[drv]; - if (!fs) return FR_NOT_ENABLED; - fs->fs_type = 0; - drv = LD2PD(drv); + /* Check mounted drive and clear work area */ + if ( drv >= _VOLUMES ) + { + return FR_INVALID_DRIVE; + } - /* Get disk statics */ - stat = disk_initialize(drv); - if (stat & STA_NOINIT) return FR_NOT_READY; - if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; -#if _MAX_SS != 512 /* Get disk sector size */ - if (disk_ioctl(drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) - return FR_DISK_ERR; -#endif - if (disk_ioctl(drv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128) - return FR_DISK_ERR; - b_vol = (sfd) ? 0 : 63; /* Volume start sector */ - n_vol -= b_vol; - if (au & (au - 1)) au = 0; /* Check validity of the allocation unit size */ - if (!au) { /* AU auto selection */ - vs = n_vol / (2000 / (SS(fs) / 512)); - for (i = 0; vs < vst[i]; i++) ; - au = cst[i]; - } - au /= SS(fs); /* Number of sectors per cluster */ - if (au == 0) au = 1; - if (au > 128) au = 128; + fs = FatFs[drv]; - /* Pre-compute number of clusters and FAT syb-type */ - n_clst = n_vol / au; - fmt = FS_FAT12; - if (n_clst >= MIN_FAT16) fmt = FS_FAT16; - if (n_clst >= MIN_FAT32) fmt = FS_FAT32; + if ( !fs ) + { + return FR_NOT_ENABLED; + } - /* Determine offset and size of FAT structure */ - if (fmt == FS_FAT32) { - n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs); - n_rsv = 32; - n_dir = 0; - } else { - n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4; - n_fat = (n_fat + SS(fs) - 1) / SS(fs); - n_rsv = 1; - n_dir = N_ROOTDIR * 32UL / SS(fs); - } - b_fat = b_vol + n_rsv; /* FAT area start sector */ - b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */ - b_data = b_dir + n_dir; /* Data area start sector */ - if (n_vol < b_data + au) return FR_MKFS_ABORTED; /* Too small volume */ + fs->fs_type = 0; + drv = LD2PD( drv ); - /* Align data start sector to erase block boundary (for flash memory media) */ - if (disk_ioctl(drv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1; - n = (b_data + n - 1) & ~(n - 1); /* Next nearest erase block from current data start */ - n = (n - b_data) / N_FATS; - if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */ - n_rsv += n; - b_fat += n; - } else { /* FAT12/16: Expand FAT size */ - n_fat += n; - } + /* Get disk statics */ + stat = disk_initialize( drv ); - /* Determine number of cluster and final check of validity of the FAT sub-type */ - n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au; - if ( (fmt == FS_FAT16 && n_clst < MIN_FAT16) - || (fmt == FS_FAT32 && n_clst < MIN_FAT32)) - return FR_MKFS_ABORTED; + if ( stat & STA_NOINIT ) + { + return FR_NOT_READY; + } - /* Create partition table if required */ - if (sfd) { - md = 0xF0; - } else { - DWORD n_disk = b_vol + n_vol; + if ( stat & STA_PROTECT ) + { + return FR_WRITE_PROTECTED; + } - mem_set(fs->win, 0, SS(fs)); - tbl = fs->win+MBR_Table; - ST_DWORD(tbl, 0x00010180); /* Partition start in CHS */ - if (n_disk < 63UL * 255 * 1024) { /* Partition end in CHS */ - n_disk = n_disk / 63 / 255; - tbl[7] = (BYTE)n_disk; - tbl[6] = (BYTE)((n_disk >> 2) | 63); - } else { - ST_WORD(&tbl[6], 0xFFFF); - } - tbl[5] = 254; - if (fmt != FS_FAT32) /* System ID */ - tbl[4] = (n_vol < 0x10000) ? 0x04 : 0x06; - else - tbl[4] = 0x0c; - ST_DWORD(tbl+8, 63); /* Partition start in LBA */ - ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */ - ST_WORD(tbl+64, 0xAA55); /* Signature */ - if (disk_write(drv, fs->win, 0, 1) != RES_OK) - return FR_DISK_ERR; - md = 0xF8; - } +#if _MAX_SS != 512 /* Get disk sector size */ - /* Create volume boot record */ - tbl = fs->win; /* Clear sector */ - mem_set(tbl, 0, SS(fs)); - mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot code, OEM name */ - i = SS(fs); /* Sector size */ - ST_WORD(tbl+BPB_BytsPerSec, i); - tbl[BPB_SecPerClus] = (BYTE)au; /* Sectors per cluster */ - ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv); /* Reserved sectors */ - tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */ - i = (fmt == FS_FAT32) ? 0 : N_ROOTDIR; /* Number of rootdir entries */ - ST_WORD(tbl+BPB_RootEntCnt, i); - if (n_vol < 0x10000) { /* Number of total sectors */ - ST_WORD(tbl+BPB_TotSec16, n_vol); - } else { - ST_DWORD(tbl+BPB_TotSec32, n_vol); - } - tbl[BPB_Media] = md; /* Media descriptor */ - ST_WORD(tbl+BPB_SecPerTrk, 63); /* Number of sectors per track */ - ST_WORD(tbl+BPB_NumHeads, 255); /* Number of heads */ - ST_DWORD(tbl+BPB_HiddSec, b_vol); /* Hidden sectors */ - n = get_fattime(); /* Use current time as VSN */ - if (fmt == FS_FAT32) { - ST_DWORD(tbl+BS_VolID32, n); /* VSN */ - ST_DWORD(tbl+BPB_FATSz32, n_fat); /* Number of sectors per FAT */ - ST_DWORD(tbl+BPB_RootClus, 2); /* Root directory start cluster (2) */ - ST_WORD(tbl+BPB_FSInfo, 1); /* FSInfo record offset (VBR+1) */ - ST_WORD(tbl+BPB_BkBootSec, 6); /* Backup boot record offset (VBR+6) */ - tbl[BS_DrvNum32] = 0x80; /* Drive number */ - tbl[BS_BootSig32] = 0x29; /* Extended boot signature */ - mem_cpy(tbl+BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */ - } else { - ST_DWORD(tbl+BS_VolID, n); /* VSN */ - ST_WORD(tbl+BPB_FATSz16, n_fat); /* Number of sectors per FAT */ - tbl[BS_DrvNum] = 0x80; /* Drive number */ - tbl[BS_BootSig] = 0x29; /* Extended boot signature */ - mem_cpy(tbl+BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ - } - ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */ - if (disk_write(drv, tbl, b_vol, 1) != RES_OK)/* Write original (VBR) */ - return FR_DISK_ERR; - if (fmt == FS_FAT32) /* Write backup (VBR+6) */ - disk_write(drv, tbl, b_vol + 6, 1); + if ( disk_ioctl( drv, GET_SECTOR_SIZE, &SS( fs ) ) != RES_OK ) + { + return FR_DISK_ERR; + } - /* Initialize FAT area */ - wsect = b_fat; - for (i = 0; i < N_FATS; i++) { - mem_set(tbl, 0, SS(fs)); /* 1st sector of the FAT */ - n = md; /* Media descriptor byte */ - if (fmt != FS_FAT32) { - n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00; - ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT12/16) */ - } else { - n |= 0xFFFFFF00; - ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT32) */ - ST_DWORD(tbl+4, 0xFFFFFFFF); - ST_DWORD(tbl+8, 0x0FFFFFFF); /* Reserve cluster #2 for root dir */ - } - if (disk_write(drv, tbl, wsect++, 1) != RES_OK) - return FR_DISK_ERR; - mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */ - for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector write */ - if (disk_write(drv, tbl, wsect++, 1) != RES_OK) - return FR_DISK_ERR; - } - } - - /* Initialize root directory */ - i = (fmt == FS_FAT32) ? au : n_dir; - do { - if (disk_write(drv, tbl, wsect++, 1) != RES_OK) - return FR_DISK_ERR; - } while (--i); - -#if _USE_ERASE /* Erase data area if needed */ - { - DWORD eb[2]; - - eb[0] = wsect; eb[1] = wsect + n_clst * au - 1; - disk_ioctl(drv, CTRL_ERASE_SECTOR, eb); - } #endif - /* Create FSInfo if needed */ - if (fmt == FS_FAT32) { - ST_WORD(tbl+BS_55AA, 0xAA55); - ST_DWORD(tbl+FSI_LeadSig, 0x41615252); - ST_DWORD(tbl+FSI_StrucSig, 0x61417272); - ST_DWORD(tbl+FSI_Free_Count, n_clst - 1); - ST_DWORD(tbl+FSI_Nxt_Free, 0xFFFFFFFF); - disk_write(drv, tbl, b_vol + 1, 1); /* Write original (VBR+1) */ - disk_write(drv, tbl, b_vol + 7, 1); /* Write backup (VBR+7) */ - } + if ( disk_ioctl( drv, GET_SECTOR_COUNT, &n_vol ) != RES_OK || n_vol < 128 ) + { + return FR_DISK_ERR; + } - return (disk_ioctl(drv, CTRL_SYNC, (void*)0) == RES_OK) ? FR_OK : FR_DISK_ERR; + b_vol = ( sfd ) ? 0 : 63; /* Volume start sector */ + n_vol -= b_vol; + + if ( au & ( au - 1 ) ) + { + au = 0; /* Check validity of the allocation unit size */ + } + + if ( !au ) /* AU auto selection */ + { + vs = n_vol / ( 2000 / ( SS( fs ) / 512 ) ); + + for ( i = 0; vs < vst[i]; i++ ) ; + + au = cst[i]; + } + + au /= SS( fs ); /* Number of sectors per cluster */ + + if ( au == 0 ) + { + au = 1; + } + + if ( au > 128 ) + { + au = 128; + } + + /* Pre-compute number of clusters and FAT syb-type */ + n_clst = n_vol / au; + fmt = FS_FAT12; + + if ( n_clst >= MIN_FAT16 ) + { + fmt = FS_FAT16; + } + + if ( n_clst >= MIN_FAT32 ) + { + fmt = FS_FAT32; + } + + /* Determine offset and size of FAT structure */ + if ( fmt == FS_FAT32 ) + { + n_fat = ( ( n_clst * 4 ) + 8 + SS( fs ) - 1 ) / SS( fs ); + n_rsv = 32; + n_dir = 0; + } + else + { + n_fat = ( fmt == FS_FAT12 ) ? ( n_clst * 3 + 1 ) / 2 + 3 : ( n_clst * 2 ) + 4; + n_fat = ( n_fat + SS( fs ) - 1 ) / SS( fs ); + n_rsv = 1; + n_dir = N_ROOTDIR * 32UL / SS( fs ); + } + + b_fat = b_vol + n_rsv; /* FAT area start sector */ + b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */ + b_data = b_dir + n_dir; /* Data area start sector */ + + if ( n_vol < b_data + au ) + { + return FR_MKFS_ABORTED; /* Too small volume */ + } + + /* Align data start sector to erase block boundary (for flash memory media) */ + if ( disk_ioctl( drv, GET_BLOCK_SIZE, &n ) != RES_OK || !n || n > 32768 ) + { + n = 1; + } + + n = ( b_data + n - 1 ) & ~( n - 1 ); /* Next nearest erase block from current data start */ + n = ( n - b_data ) / N_FATS; + + if ( fmt == FS_FAT32 ) /* FAT32: Move FAT offset */ + { + n_rsv += n; + b_fat += n; + } + else /* FAT12/16: Expand FAT size */ + { + n_fat += n; + } + + /* Determine number of cluster and final check of validity of the FAT sub-type */ + n_clst = ( n_vol - n_rsv - n_fat * N_FATS - n_dir ) / au; + + if ( ( fmt == FS_FAT16 && n_clst < MIN_FAT16 ) + || ( fmt == FS_FAT32 && n_clst < MIN_FAT32 ) ) + { + return FR_MKFS_ABORTED; + } + + /* Create partition table if required */ + if ( sfd ) + { + md = 0xF0; + } + else + { + DWORD n_disk = b_vol + n_vol; + + mem_set( fs->win, 0, SS( fs ) ); + tbl = fs->win + MBR_Table; + ST_DWORD( tbl, 0x00010180 ); /* Partition start in CHS */ + + if ( n_disk < 63UL * 255 * 1024 ) /* Partition end in CHS */ + { + n_disk = n_disk / 63 / 255; + tbl[7] = ( BYTE )n_disk; + tbl[6] = ( BYTE )( ( n_disk >> 2 ) | 63 ); + } + else + { + ST_WORD( &tbl[6], 0xFFFF ); + } + + tbl[5] = 254; + + if ( fmt != FS_FAT32 ) /* System ID */ + { + tbl[4] = ( n_vol < 0x10000 ) ? 0x04 : 0x06; + } + else + { + tbl[4] = 0x0c; + } + + ST_DWORD( tbl + 8, 63 ); /* Partition start in LBA */ + ST_DWORD( tbl + 12, n_vol ); /* Partition size in LBA */ + ST_WORD( tbl + 64, 0xAA55 ); /* Signature */ + + if ( disk_write( drv, fs->win, 0, 1 ) != RES_OK ) + { + return FR_DISK_ERR; + } + + md = 0xF8; + } + + /* Create volume boot record */ + tbl = fs->win; /* Clear sector */ + mem_set( tbl, 0, SS( fs ) ); + mem_cpy( tbl, "\xEB\xFE\x90" "MSDOS5.0", 11 ); /* Boot code, OEM name */ + i = SS( fs ); /* Sector size */ + ST_WORD( tbl + BPB_BytsPerSec, i ); + tbl[BPB_SecPerClus] = ( BYTE )au; /* Sectors per cluster */ + ST_WORD( tbl + BPB_RsvdSecCnt, n_rsv ); /* Reserved sectors */ + tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */ + i = ( fmt == FS_FAT32 ) ? 0 : N_ROOTDIR; /* Number of rootdir entries */ + ST_WORD( tbl + BPB_RootEntCnt, i ); + + if ( n_vol < 0x10000 ) /* Number of total sectors */ + { + ST_WORD( tbl + BPB_TotSec16, n_vol ); + } + else + { + ST_DWORD( tbl + BPB_TotSec32, n_vol ); + } + + tbl[BPB_Media] = md; /* Media descriptor */ + ST_WORD( tbl + BPB_SecPerTrk, 63 ); /* Number of sectors per track */ + ST_WORD( tbl + BPB_NumHeads, 255 ); /* Number of heads */ + ST_DWORD( tbl + BPB_HiddSec, b_vol ); /* Hidden sectors */ + n = get_fattime(); /* Use current time as VSN */ + + if ( fmt == FS_FAT32 ) + { + ST_DWORD( tbl + BS_VolID32, n ); /* VSN */ + ST_DWORD( tbl + BPB_FATSz32, n_fat ); /* Number of sectors per FAT */ + ST_DWORD( tbl + BPB_RootClus, 2 ); /* Root directory start cluster (2) */ + ST_WORD( tbl + BPB_FSInfo, 1 ); /* FSInfo record offset (VBR+1) */ + ST_WORD( tbl + BPB_BkBootSec, 6 ); /* Backup boot record offset (VBR+6) */ + tbl[BS_DrvNum32] = 0x80; /* Drive number */ + tbl[BS_BootSig32] = 0x29; /* Extended boot signature */ + mem_cpy( tbl + BS_VolLab32, "NO NAME " "FAT32 ", 19 ); /* Volume label, FAT signature */ + } + else + { + ST_DWORD( tbl + BS_VolID, n ); /* VSN */ + ST_WORD( tbl + BPB_FATSz16, n_fat ); /* Number of sectors per FAT */ + tbl[BS_DrvNum] = 0x80; /* Drive number */ + tbl[BS_BootSig] = 0x29; /* Extended boot signature */ + mem_cpy( tbl + BS_VolLab, "NO NAME " "FAT ", 19 ); /* Volume label, FAT signature */ + } + + ST_WORD( tbl + BS_55AA, 0xAA55 ); /* Signature (Offset is fixed here regardless of sector size) */ + + if ( disk_write( drv, tbl, b_vol, 1 ) != RES_OK ) /* Write original (VBR) */ + { + return FR_DISK_ERR; + } + + if ( fmt == FS_FAT32 ) /* Write backup (VBR+6) */ + { + disk_write( drv, tbl, b_vol + 6, 1 ); + } + + /* Initialize FAT area */ + wsect = b_fat; + + for ( i = 0; i < N_FATS; i++ ) + { + mem_set( tbl, 0, SS( fs ) ); /* 1st sector of the FAT */ + n = md; /* Media descriptor byte */ + + if ( fmt != FS_FAT32 ) + { + n |= ( fmt == FS_FAT12 ) ? 0x00FFFF00 : 0xFFFFFF00; + ST_DWORD( tbl + 0, n ); /* Reserve cluster #0-1 (FAT12/16) */ + } + else + { + n |= 0xFFFFFF00; + ST_DWORD( tbl + 0, n ); /* Reserve cluster #0-1 (FAT32) */ + ST_DWORD( tbl + 4, 0xFFFFFFFF ); + ST_DWORD( tbl + 8, 0x0FFFFFFF ); /* Reserve cluster #2 for root dir */ + } + + if ( disk_write( drv, tbl, wsect++, 1 ) != RES_OK ) + { + return FR_DISK_ERR; + } + + mem_set( tbl, 0, SS( fs ) ); /* Fill following FAT entries with zero */ + + for ( n = 1; n < n_fat; n++ ) /* This loop may take a time on FAT32 volume due to many single sector write */ + { + if ( disk_write( drv, tbl, wsect++, 1 ) != RES_OK ) + { + return FR_DISK_ERR; + } + } + } + + /* Initialize root directory */ + i = ( fmt == FS_FAT32 ) ? au : n_dir; + + do + { + if ( disk_write( drv, tbl, wsect++, 1 ) != RES_OK ) + { + return FR_DISK_ERR; + } + } + while ( --i ); + +#if _USE_ERASE /* Erase data area if needed */ + { + DWORD eb[2]; + + eb[0] = wsect; eb[1] = wsect + n_clst * au - 1; + disk_ioctl( drv, CTRL_ERASE_SECTOR, eb ); + } +#endif + + /* Create FSInfo if needed */ + if ( fmt == FS_FAT32 ) + { + ST_WORD( tbl + BS_55AA, 0xAA55 ); + ST_DWORD( tbl + FSI_LeadSig, 0x41615252 ); + ST_DWORD( tbl + FSI_StrucSig, 0x61417272 ); + ST_DWORD( tbl + FSI_Free_Count, n_clst - 1 ); + ST_DWORD( tbl + FSI_Nxt_Free, 0xFFFFFFFF ); + disk_write( drv, tbl, b_vol + 1, 1 ); /* Write original (VBR+1) */ + disk_write( drv, tbl, b_vol + 7, 1 ); /* Write backup (VBR+7) */ + } + + return ( disk_ioctl( drv, CTRL_SYNC, ( void * )0 ) == RES_OK ) ? FR_OK : FR_DISK_ERR; } #endif /* _USE_MKFS && !_FS_READONLY */ @@ -3545,51 +5421,98 @@ FRESULT f_mkfs ( /*-----------------------------------------------------------------------*/ /* Get a string from the file */ /*-----------------------------------------------------------------------*/ -TCHAR* f_gets ( - TCHAR* buff, /* Pointer to the string buffer to read */ - int len, /* Size of string buffer (characters) */ - FIL* fil /* Pointer to the file object */ +TCHAR *f_gets ( + TCHAR *buff, /* Pointer to the string buffer to read */ + int len, /* Size of string buffer (characters) */ + FIL *fil /* Pointer to the file object */ ) { - int n = 0; - TCHAR c, *p = buff; - BYTE s[2]; - UINT rc; + int n = 0; + TCHAR c, *p = buff; + BYTE s[2]; + UINT rc; - while (n < len - 1) { /* Read bytes until buffer gets filled */ - f_read(fil, s, 1, &rc); - if (rc != 1) break; /* Break on EOF or error */ - c = s[0]; -#if _LFN_UNICODE /* Read a character in UTF-8 encoding */ - if (c >= 0x80) { - if (c < 0xC0) continue; /* Skip stray trailer */ - if (c < 0xE0) { /* Two-byte sequense */ - f_read(fil, s, 1, &rc); - if (rc != 1) break; - c = ((c & 0x1F) << 6) | (s[0] & 0x3F); - if (c < 0x80) c = '?'; - } else { - if (c < 0xF0) { /* Three-byte sequense */ - f_read(fil, s, 2, &rc); - if (rc != 2) break; - c = (c << 12) | ((s[0] & 0x3F) << 6) | (s[1] & 0x3F); - if (c < 0x800) c = '?'; - } else { /* Reject four-byte sequense */ - c = '?'; - } - } - } + while ( n < len - 1 ) /* Read bytes until buffer gets filled */ + { + f_read( fil, s, 1, &rc ); + + if ( rc != 1 ) + { + break; /* Break on EOF or error */ + } + + c = s[0]; +#if _LFN_UNICODE /* Read a character in UTF-8 encoding */ + + if ( c >= 0x80 ) + { + if ( c < 0xC0 ) + { + continue; /* Skip stray trailer */ + } + + if ( c < 0xE0 ) /* Two-byte sequense */ + { + f_read( fil, s, 1, &rc ); + + if ( rc != 1 ) + { + break; + } + + c = ( ( c & 0x1F ) << 6 ) | ( s[0] & 0x3F ); + + if ( c < 0x80 ) + { + c = '?'; + } + } + else + { + if ( c < 0xF0 ) /* Three-byte sequense */ + { + f_read( fil, s, 2, &rc ); + + if ( rc != 2 ) + { + break; + } + + c = ( c << 12 ) | ( ( s[0] & 0x3F ) << 6 ) | ( s[1] & 0x3F ); + + if ( c < 0x800 ) + { + c = '?'; + } + } + else /* Reject four-byte sequense */ + { + c = '?'; + } + } + } + #endif #if _USE_STRFUNC >= 2 - if (c == '\r') continue; /* Strip '\r' */ + + if ( c == '\r' ) + { + continue; /* Strip '\r' */ + } + #endif - *p++ = c; - n++; - if (c == '\n') break; /* Break on EOL */ - } - *p = 0; - return n ? buff : 0; /* When no data read (eof or error), return with error. */ + *p++ = c; + n++; + + if ( c == '\n' ) + { + break; /* Break on EOL */ + } + } + + *p = 0; + return n ? buff : 0; /* When no data read (eof or error), return with error. */ } @@ -3600,40 +5523,53 @@ TCHAR* f_gets ( /* Put a character to the file */ /*-----------------------------------------------------------------------*/ int f_putc ( - TCHAR c, /* A character to be output */ - FIL* fil /* Pointer to the file object */ + TCHAR c, /* A character to be output */ + FIL *fil /* Pointer to the file object */ ) { - UINT bw, btw; - BYTE s[3]; + UINT bw, btw; + BYTE s[3]; #if _USE_STRFUNC >= 2 - if (c == '\n') f_putc ('\r', fil); /* LF -> CRLF conversion */ + + if ( c == '\n' ) + { + f_putc ( '\r', fil ); /* LF -> CRLF conversion */ + } + #endif -#if _LFN_UNICODE /* Write the character in UTF-8 encoding */ - if (c < 0x80) { /* 7-bit */ - s[0] = (BYTE)c; - btw = 1; - } else { - if (c < 0x800) { /* 11-bit */ - s[0] = (BYTE)(0xC0 | (c >> 6)); - s[1] = (BYTE)(0x80 | (c & 0x3F)); - btw = 2; - } else { /* 16-bit */ - s[0] = (BYTE)(0xE0 | (c >> 12)); - s[1] = (BYTE)(0x80 | ((c >> 6) & 0x3F)); - s[2] = (BYTE)(0x80 | (c & 0x3F)); - btw = 3; - } - } -#else /* Write the character without conversion */ - s[0] = (BYTE)c; - btw = 1; +#if _LFN_UNICODE /* Write the character in UTF-8 encoding */ + + if ( c < 0x80 ) /* 7-bit */ + { + s[0] = ( BYTE )c; + btw = 1; + } + else + { + if ( c < 0x800 ) /* 11-bit */ + { + s[0] = ( BYTE )( 0xC0 | ( c >> 6 ) ); + s[1] = ( BYTE )( 0x80 | ( c & 0x3F ) ); + btw = 2; + } + else /* 16-bit */ + { + s[0] = ( BYTE )( 0xE0 | ( c >> 12 ) ); + s[1] = ( BYTE )( 0x80 | ( ( c >> 6 ) & 0x3F ) ); + s[2] = ( BYTE )( 0x80 | ( c & 0x3F ) ); + btw = 3; + } + } + +#else /* Write the character without conversion */ + s[0] = ( BYTE )c; + btw = 1; #endif - f_write(fil, s, btw, &bw); /* Write the char to the file */ - return (bw == btw) ? 1 : EOF; /* Return the result */ + f_write( fil, s, btw, &bw ); /* Write the char to the file */ + return ( bw == btw ) ? 1 : EOF; /* Return the result */ } @@ -3643,17 +5579,22 @@ int f_putc ( /* Put a string to the file */ /*-----------------------------------------------------------------------*/ int f_puts ( - const TCHAR* str, /* Pointer to the string to be output */ - FIL* fil /* Pointer to the file object */ + const TCHAR *str, /* Pointer to the string to be output */ + FIL *fil /* Pointer to the file object */ ) { - int n; + int n; - for (n = 0; *str; str++, n++) { - if (f_putc(*str, fil) == EOF) return EOF; - } - return n; + for ( n = 0; *str; str++, n++ ) + { + if ( f_putc( *str, fil ) == EOF ) + { + return EOF; + } + } + + return n; } @@ -3663,93 +5604,156 @@ int f_puts ( /* Put a formatted string to the file */ /*-----------------------------------------------------------------------*/ int f_printf ( - FIL* fil, /* Pointer to the file object */ - const TCHAR* str, /* Pointer to the format string */ - ... /* Optional arguments... */ + FIL *fil, /* Pointer to the file object */ + const TCHAR *str, /* Pointer to the format string */ + ... /* Optional arguments... */ ) { - va_list arp; - BYTE f, r; - UINT i, w; - ULONG val; - TCHAR c, d, s[16]; - int res, cc; + va_list arp; + BYTE f, r; + UINT i, w; + ULONG val; + TCHAR c, d, s[16]; + int res, cc; - va_start(arp, str); + va_start( arp, str ); - for (cc = res = 0; cc != EOF; res += cc) { - c = *str++; - if (c == 0) break; /* End of string */ - if (c != '%') { /* Non escape character */ - cc = f_putc(c, fil); - if (cc != EOF) cc = 1; - continue; - } - w = f = 0; - c = *str++; - if (c == '0') { /* Flag: '0' padding */ - f = 1; c = *str++; - } - while (IsDigit(c)) { /* Precision */ - w = w * 10 + c - '0'; - c = *str++; - } - if (c == 'l' || c == 'L') { /* Prefix: Size is long int */ - f |= 2; c = *str++; - } - if (!c) break; - d = c; - if (IsLower(d)) d -= 0x20; - switch (d) { /* Type is... */ - case 'S' : /* String */ - cc = f_puts(va_arg(arp, TCHAR*), fil); continue; - case 'C' : /* Character */ - cc = f_putc((TCHAR)va_arg(arp, int), fil); continue; - case 'B' : /* Binary */ - r = 2; break; - case 'O' : /* Octal */ - r = 8; break; - case 'D' : /* Signed decimal */ - case 'U' : /* Unsigned decimal */ - r = 10; break; - case 'X' : /* Hexdecimal */ - r = 16; break; - default: /* Unknown */ - cc = f_putc(c, fil); continue; - } + for ( cc = res = 0; cc != EOF; res += cc ) + { + c = *str++; - /* Get an argument */ - val = (f & 2) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : va_arg(arp, unsigned int)); - if (d == 'D' && (val & 0x80000000)) { - val = 0 - val; - f |= 4; - } - /* Put it in numeral string */ - i = 0; - do { - d = (TCHAR)(val % r); val /= r; - if (d > 9) { - d += 7; - if (c == 'x') d += 0x20; - } - s[i++] = d + '0'; - } while (val && i < sizeof(s) / sizeof(s[0])); - if (f & 4) s[i++] = '-'; - cc = 0; - while (i < w-- && cc != EOF) { - cc = f_putc((TCHAR)((f & 1) ? '0' : ' '), fil); - res++; - } - do { - cc = f_putc(s[--i], fil); - res++; - } while (i && cc != EOF); - if (cc != EOF) cc = 0; - } + if ( c == 0 ) + { + break; /* End of string */ + } - va_end(arp); - return (cc == EOF) ? cc : res; + if ( c != '%' ) /* Non escape character */ + { + cc = f_putc( c, fil ); + + if ( cc != EOF ) + { + cc = 1; + } + + continue; + } + + w = f = 0; + c = *str++; + + if ( c == '0' ) /* Flag: '0' padding */ + { + f = 1; c = *str++; + } + + while ( IsDigit( c ) ) /* Precision */ + { + w = w * 10 + c - '0'; + c = *str++; + } + + if ( c == 'l' || c == 'L' ) /* Prefix: Size is long int */ + { + f |= 2; c = *str++; + } + + if ( !c ) + { + break; + } + + d = c; + + if ( IsLower( d ) ) + { + d -= 0x20; + } + + switch ( d ) /* Type is... */ + { + case 'S' : /* String */ + cc = f_puts( va_arg( arp, TCHAR * ), fil ); continue; + + case 'C' : /* Character */ + cc = f_putc( ( TCHAR )va_arg( arp, int ), fil ); continue; + + case 'B' : /* Binary */ + r = 2; break; + + case 'O' : /* Octal */ + r = 8; break; + + case 'D' : /* Signed decimal */ + case 'U' : /* Unsigned decimal */ + r = 10; break; + + case 'X' : /* Hexdecimal */ + r = 16; break; + + default: /* Unknown */ + cc = f_putc( c, fil ); continue; + } + + /* Get an argument */ + val = ( f & 2 ) ? va_arg( arp, long ) : ( ( d == 'D' ) ? ( long )va_arg( arp, int ) : va_arg( arp, unsigned int ) ); + + if ( d == 'D' && ( val & 0x80000000 ) ) + { + val = 0 - val; + f |= 4; + } + + /* Put it in numeral string */ + i = 0; + + do + { + d = ( TCHAR )( val % r ); val /= r; + + if ( d > 9 ) + { + d += 7; + + if ( c == 'x' ) + { + d += 0x20; + } + } + + s[i++] = d + '0'; + } + while ( val && i < sizeof( s ) / sizeof( s[0] ) ); + + if ( f & 4 ) + { + s[i++] = '-'; + } + + cc = 0; + + while ( i < w-- && cc != EOF ) + { + cc = f_putc( ( TCHAR )( ( f & 1 ) ? '0' : ' ' ), fil ); + res++; + } + + do + { + cc = f_putc( s[--i], fil ); + res++; + } + while ( i && cc != EOF ); + + if ( cc != EOF ) + { + cc = 0; + } + } + + va_end( arp ); + return ( cc == EOF ) ? cc : res; } #endif /* !_FS_READONLY */ diff --git a/src/bootldr/ff.h b/src/bootldr/ff.h index 438fa14..6e74e09 100644 --- a/src/bootldr/ff.h +++ b/src/bootldr/ff.h @@ -15,14 +15,14 @@ /----------------------------------------------------------------------------*/ #ifndef _FATFS -#define _FATFS 8255 /* Revision ID */ +#define _FATFS 8255 /* Revision ID */ #ifdef __cplusplus extern "C" { #endif -#include "integer.h" /* Basic integer types */ -#include "ffconf.h" /* FatFs configuration options */ +#include "integer.h" /* Basic integer types */ +#include "ffconf.h" /* FatFs configuration options */ #if _FATFS != _FFCONF #error Wrong configuration file (ffconf.h). @@ -31,191 +31,191 @@ extern "C" { /* DBCS code ranges and SBCS extend char conversion table */ -#if _CODE_PAGE == 932 /* Japanese Shift-JIS */ -#define _DF1S 0x81 /* DBC 1st byte range 1 start */ -#define _DF1E 0x9F /* DBC 1st byte range 1 end */ -#define _DF2S 0xE0 /* DBC 1st byte range 2 start */ -#define _DF2E 0xFC /* DBC 1st byte range 2 end */ -#define _DS1S 0x40 /* DBC 2nd byte range 1 start */ -#define _DS1E 0x7E /* DBC 2nd byte range 1 end */ -#define _DS2S 0x80 /* DBC 2nd byte range 2 start */ -#define _DS2E 0xFC /* DBC 2nd byte range 2 end */ +#if _CODE_PAGE == 932 /* Japanese Shift-JIS */ +#define _DF1S 0x81 /* DBC 1st byte range 1 start */ +#define _DF1E 0x9F /* DBC 1st byte range 1 end */ +#define _DF2S 0xE0 /* DBC 1st byte range 2 start */ +#define _DF2E 0xFC /* DBC 1st byte range 2 end */ +#define _DS1S 0x40 /* DBC 2nd byte range 1 start */ +#define _DS1E 0x7E /* DBC 2nd byte range 1 end */ +#define _DS2S 0x80 /* DBC 2nd byte range 2 start */ +#define _DS2E 0xFC /* DBC 2nd byte range 2 end */ -#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */ -#define _DF1S 0x81 -#define _DF1E 0xFE -#define _DS1S 0x40 -#define _DS1E 0x7E -#define _DS2S 0x80 -#define _DS2E 0xFE +#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x40 +#define _DS1E 0x7E +#define _DS2S 0x80 +#define _DS2E 0xFE -#elif _CODE_PAGE == 949 /* Korean */ -#define _DF1S 0x81 -#define _DF1E 0xFE -#define _DS1S 0x41 -#define _DS1E 0x5A -#define _DS2S 0x61 -#define _DS2E 0x7A -#define _DS3S 0x81 -#define _DS3E 0xFE +#elif _CODE_PAGE == 949 /* Korean */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x41 +#define _DS1E 0x5A +#define _DS2S 0x61 +#define _DS2E 0x7A +#define _DS3S 0x81 +#define _DS3E 0xFE -#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */ -#define _DF1S 0x81 -#define _DF1E 0xFE -#define _DS1S 0x40 -#define _DS1E 0x7E -#define _DS2S 0xA1 -#define _DS2E 0xFE +#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x40 +#define _DS1E 0x7E +#define _DS2S 0xA1 +#define _DS2E 0xFE -#elif _CODE_PAGE == 437 /* U.S. (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 437 /* U.S. (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 720 /* Arabic (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 720 /* Arabic (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 737 /* Greek (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 737 /* Greek (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ - 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 775 /* Baltic (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 775 /* Baltic (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \ - 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} + 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} -#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */ +#define _DF1S 0 #define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ - 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ - 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} + 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ + 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 857 /* Turkish (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 857 /* Turkish (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ - 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 862 /* Hebrew (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 862 /* Hebrew (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 866 /* Russian (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 866 /* Russian (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */ -#define _DF1S 0 +#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */ +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} #elif _CODE_PAGE == 1250 /* Central Europe (Windows) */ -#define _DF1S 0 +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} #elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */ -#define _DF1S 0 +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ - 0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF} + 0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF} #elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */ -#define _DF1S 0 +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} #elif _CODE_PAGE == 1253 /* Greek (Windows) */ -#define _DF1S 0 +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \ - 0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF} + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \ + 0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF} #elif _CODE_PAGE == 1254 /* Turkish (Windows) */ -#define _DF1S 0 +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} #elif _CODE_PAGE == 1255 /* Hebrew (Windows) */ -#define _DF1S 0 +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} #elif _CODE_PAGE == 1256 /* Arabic (Windows) */ -#define _DF1S 0 +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF} + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF} #elif _CODE_PAGE == 1257 /* Baltic (Windows) */ -#define _DF1S 0 +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} #elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */ -#define _DF1S 0 +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F} + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F} -#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */ -#define _DF1S 0 +#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */ +#define _DF1S 0 #else #error Unknown code page @@ -226,18 +226,19 @@ extern "C" { /* Definitions of volume management */ -#if _MULTI_PARTITION /* Multiple partition configuration */ -#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive# */ -#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition# */ -typedef struct { - BYTE pd; /* Physical drive# */ - BYTE pt; /* Partition # (0-3) */ +#if _MULTI_PARTITION /* Multiple partition configuration */ +#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive# */ +#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition# */ +typedef struct +{ + BYTE pd; /* Physical drive# */ + BYTE pt; /* Partition # (0-3) */ } PARTITION; -extern const PARTITION VolToPart[]; /* Volume - Physical location resolution table */ +extern const PARTITION VolToPart[]; /* Volume - Physical location resolution table */ -#else /* Single partition configuration */ -#define LD2PD(vol) (vol) /* Logical drive# is bound to the same physical drive# */ -#define LD2PT(vol) 0 /* Always mounts the 1st partition */ +#else /* Single partition configuration */ +#define LD2PD(vol) (vol) /* Logical drive# is bound to the same physical drive# */ +#define LD2PT(vol) 0 /* Always mounts the 1st partition */ #endif @@ -245,7 +246,7 @@ extern const PARTITION VolToPart[]; /* Volume - Physical location resolution tab /* Type of path name strings on FatFs API */ -#if _LFN_UNICODE /* Unicode string */ +#if _LFN_UNICODE /* Unicode string */ #if !_USE_LFN #error _LFN_UNICODE must be 0 in non-LFN cfg. #endif @@ -255,7 +256,7 @@ typedef WCHAR TCHAR; #define _TEXT(x) L ## x #endif -#else /* ANSI/OEM string */ +#else /* ANSI/OEM string */ #ifndef _INC_TCHAR typedef char TCHAR; #define _T(x) x @@ -268,64 +269,66 @@ typedef char TCHAR; /* File system object structure (FATFS) */ -typedef struct { - BYTE fs_type; /* FAT sub-type (0:Not mounted) */ - BYTE drv; /* Physical drive number */ - BYTE csize; /* Sectors per cluster (1,2,4...128) */ - BYTE n_fats; /* Number of FAT copies (1,2) */ - BYTE wflag; /* win[] dirty flag (1:must be written back) */ - BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */ - WORD id; /* File system mount ID */ - WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ +typedef struct +{ + BYTE fs_type; /* FAT sub-type (0:Not mounted) */ + BYTE drv; /* Physical drive number */ + BYTE csize; /* Sectors per cluster (1,2,4...128) */ + BYTE n_fats; /* Number of FAT copies (1,2) */ + BYTE wflag; /* win[] dirty flag (1:must be written back) */ + BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */ + WORD id; /* File system mount ID */ + WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ #if _MAX_SS != 512 - WORD ssize; /* Bytes per sector (512,1024,2048,4096) */ + WORD ssize; /* Bytes per sector (512,1024,2048,4096) */ #endif #if _FS_REENTRANT - _SYNC_t sobj; /* Identifier of sync object */ + _SYNC_t sobj; /* Identifier of sync object */ #endif #if !_FS_READONLY - DWORD last_clust; /* Last allocated cluster */ - DWORD free_clust; /* Number of free clusters */ - DWORD fsi_sector; /* fsinfo sector (FAT32) */ + DWORD last_clust; /* Last allocated cluster */ + DWORD free_clust; /* Number of free clusters */ + DWORD fsi_sector; /* fsinfo sector (FAT32) */ #endif #if _FS_RPATH - DWORD cdir; /* Current directory start cluster (0:root) */ + DWORD cdir; /* Current directory start cluster (0:root) */ #endif - DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */ - DWORD fsize; /* Sectors per FAT */ - DWORD fatbase; /* FAT start sector */ - DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */ - DWORD database; /* Data start sector */ - DWORD winsect; /* Current sector appearing in the win[] */ - BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */ + DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */ + DWORD fsize; /* Sectors per FAT */ + DWORD fatbase; /* FAT start sector */ + DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */ + DWORD database; /* Data start sector */ + DWORD winsect; /* Current sector appearing in the win[] */ + BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */ } FATFS; /* File object structure (FIL) */ -typedef struct { - FATFS* fs; /* Pointer to the owner file system object */ - WORD id; /* Owner file system mount ID */ - BYTE flag; /* File status flags */ - BYTE pad1; - DWORD fptr; /* File read/write pointer (0 on file open) */ - DWORD fsize; /* File size */ - DWORD org_clust; /* File start cluster (0 when fsize==0) */ - DWORD curr_clust; /* Current cluster */ - DWORD dsect; /* Current data sector */ +typedef struct +{ + FATFS *fs; /* Pointer to the owner file system object */ + WORD id; /* Owner file system mount ID */ + BYTE flag; /* File status flags */ + BYTE pad1; + DWORD fptr; /* File read/write pointer (0 on file open) */ + DWORD fsize; /* File size */ + DWORD org_clust; /* File start cluster (0 when fsize==0) */ + DWORD curr_clust; /* Current cluster */ + DWORD dsect; /* Current data sector */ #if !_FS_READONLY - DWORD dir_sect; /* Sector containing the directory entry */ - BYTE* dir_ptr; /* Ponter to the directory entry in the window */ + DWORD dir_sect; /* Sector containing the directory entry */ + BYTE *dir_ptr; /* Ponter to the directory entry in the window */ #endif #if _USE_FASTSEEK - DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */ + DWORD *cltbl; /* Pointer to the cluster link map table (null on file open) */ #endif #if _FS_SHARE - UINT lockid; /* File lock ID (index of file semaphore table) */ + UINT lockid; /* File lock ID (index of file semaphore table) */ #endif #if !_FS_TINY - BYTE buf[_MAX_SS]; /* File data read/write buffer */ + BYTE buf[_MAX_SS]; /* File data read/write buffer */ #endif } FIL; @@ -333,18 +336,19 @@ typedef struct { /* Directory object structure (DIR) */ -typedef struct { - FATFS* fs; /* Pointer to the owner file system object */ - WORD id; /* Owner file system mount ID */ - WORD index; /* Current read/write index number */ - DWORD sclust; /* Table start cluster (0:Root dir) */ - DWORD clust; /* Current cluster */ - DWORD sect; /* Current sector */ - BYTE* dir; /* Pointer to the current SFN entry in the win[] */ - BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */ +typedef struct +{ + FATFS *fs; /* Pointer to the owner file system object */ + WORD id; /* Owner file system mount ID */ + WORD index; /* Current read/write index number */ + DWORD sclust; /* Table start cluster (0:Root dir) */ + DWORD clust; /* Current cluster */ + DWORD sect; /* Current sector */ + BYTE *dir; /* Pointer to the current SFN entry in the win[] */ + BYTE *fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */ #if _USE_LFN - WCHAR* lfn; /* Pointer to the LFN working buffer */ - WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */ + WCHAR *lfn; /* Pointer to the LFN working buffer */ + WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */ #endif } DIR; @@ -352,16 +356,17 @@ typedef struct { /* File status structure (FILINFO) */ -typedef struct { - DWORD fsize; /* File size */ - WORD fdate; /* Last modified date */ - WORD ftime; /* Last modified time */ - BYTE fattrib; /* Attribute */ - TCHAR fname[13]; /* Short file name (8.3 format) */ - DWORD clust; /* start cluster */ +typedef struct +{ + DWORD fsize; /* File size */ + WORD fdate; /* Last modified date */ + WORD ftime; /* Last modified time */ + BYTE fattrib; /* Attribute */ + TCHAR fname[13]; /* Short file name (8.3 format) */ + DWORD clust; /* start cluster */ #if _USE_LFN - TCHAR* lfname; /* Pointer to the LFN buffer */ - UINT lfsize; /* Size of LFN buffer in TCHAR */ + TCHAR *lfname; /* Pointer to the LFN buffer */ + UINT lfsize; /* Size of LFN buffer in TCHAR */ #endif } FILINFO; @@ -369,26 +374,27 @@ typedef struct { /* File function return code (FRESULT) */ -typedef enum { - FR_OK = 0, /* (0) Succeeded */ - FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */ - FR_INT_ERR, /* (2) Assertion failed */ - FR_NOT_READY, /* (3) The physical drive cannot work */ - FR_NO_FILE, /* (4) Could not find the file */ - FR_NO_PATH, /* (5) Could not find the path */ - FR_INVALID_NAME, /* (6) The path name format is invalid */ - FR_DENIED, /* (7) Acces denied due to prohibited access or directory full */ - FR_EXIST, /* (8) Acces denied due to prohibited access */ - FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ - FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ - FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ - FR_NOT_ENABLED, /* (12) The volume has no work area */ - FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume on the physical drive */ - FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ - FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ - FR_LOCKED, /* (16) The operation is rejected according to the file shareing policy */ - FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ - FR_TOO_MANY_OPEN_FILES /* (18) Number of open files > _FS_SHARE */ +typedef enum +{ + FR_OK = 0, /* (0) Succeeded */ + FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */ + FR_INT_ERR, /* (2) Assertion failed */ + FR_NOT_READY, /* (3) The physical drive cannot work */ + FR_NO_FILE, /* (4) Could not find the file */ + FR_NO_PATH, /* (5) Could not find the path */ + FR_INVALID_NAME, /* (6) The path name format is invalid */ + FR_DENIED, /* (7) Acces denied due to prohibited access or directory full */ + FR_EXIST, /* (8) Acces denied due to prohibited access */ + FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ + FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ + FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ + FR_NOT_ENABLED, /* (12) The volume has no work area */ + FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume on the physical drive */ + FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ + FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ + FR_LOCKED, /* (16) The operation is rejected according to the file shareing policy */ + FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ + FR_TOO_MANY_OPEN_FILES /* (18) Number of open files > _FS_SHARE */ } FRESULT; @@ -397,49 +403,50 @@ typedef enum { /* FatFs module application interface */ /* Low Level functions */ -FRESULT l_openfilebycluster(FATFS *fs, FIL *fp, const TCHAR *path, DWORD clust, DWORD fsize); /* Open a file by its start cluster using supplied file size */ +FRESULT l_openfilebycluster( FATFS *fs, FIL *fp, const TCHAR *path, DWORD clust, + DWORD fsize ); /* Open a file by its start cluster using supplied file size */ /* application level functions */ -FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */ -FRESULT f_open (FIL*, const TCHAR*, BYTE); /* Open or create a file */ -FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */ -FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */ -FRESULT f_close (FIL*); /* Close an open file object */ -FRESULT f_opendir (DIR*, const TCHAR*); /* Open an existing directory */ -FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */ -FRESULT f_stat (const TCHAR*, FILINFO*); /* Get file status */ +FRESULT f_mount ( BYTE, FATFS * ); /* Mount/Unmount a logical drive */ +FRESULT f_open ( FIL *, const TCHAR *, BYTE ); /* Open or create a file */ +FRESULT f_read ( FIL *, void *, UINT, UINT * ); /* Read data from a file */ +FRESULT f_lseek ( FIL *, DWORD ); /* Move file pointer of a file object */ +FRESULT f_close ( FIL * ); /* Close an open file object */ +FRESULT f_opendir ( DIR *, const TCHAR * ); /* Open an existing directory */ +FRESULT f_readdir ( DIR *, FILINFO * ); /* Read a directory item */ +FRESULT f_stat ( const TCHAR *, FILINFO * ); /* Get file status */ #if !_FS_READONLY -FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */ -FRESULT f_getfree (const TCHAR*, DWORD*, FATFS**); /* Get number of free clusters on the drive */ -FRESULT f_truncate (FIL*); /* Truncate file */ -FRESULT f_sync (FIL*); /* Flush cached data of a writing file */ -FRESULT f_unlink (const TCHAR*); /* Delete an existing file or directory */ -FRESULT f_mkdir (const TCHAR*); /* Create a new directory */ -FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attriburte of the file/dir */ -FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change timestamp of the file/dir */ -FRESULT f_rename (const TCHAR*, const TCHAR*); /* Rename/Move a file or directory */ +FRESULT f_write ( FIL *, const void *, UINT, UINT * ); /* Write data to a file */ +FRESULT f_getfree ( const TCHAR *, DWORD *, FATFS ** ); /* Get number of free clusters on the drive */ +FRESULT f_truncate ( FIL * ); /* Truncate file */ +FRESULT f_sync ( FIL * ); /* Flush cached data of a writing file */ +FRESULT f_unlink ( const TCHAR * ); /* Delete an existing file or directory */ +FRESULT f_mkdir ( const TCHAR * ); /* Create a new directory */ +FRESULT f_chmod ( const TCHAR *, BYTE, BYTE ); /* Change attriburte of the file/dir */ +FRESULT f_utime ( const TCHAR *, const FILINFO * ); /* Change timestamp of the file/dir */ +FRESULT f_rename ( const TCHAR *, const TCHAR * ); /* Rename/Move a file or directory */ #endif #if _USE_FORWARD -FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */ +FRESULT f_forward ( FIL *, UINT( * )( const BYTE *, UINT ), UINT, UINT * ); /* Forward data to the stream */ #endif #if _USE_MKFS -FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */ +FRESULT f_mkfs ( BYTE, BYTE, UINT ); /* Create a file system on the drive */ #endif #if _FS_RPATH -FRESULT f_chdrive (BYTE); /* Change current drive */ -FRESULT f_chdir (const TCHAR*); /* Change current directory */ -FRESULT f_getcwd (TCHAR*, UINT); /* Get current directory */ +FRESULT f_chdrive ( BYTE ); /* Change current drive */ +FRESULT f_chdir ( const TCHAR * ); /* Change current directory */ +FRESULT f_getcwd ( TCHAR *, UINT ); /* Get current directory */ #endif #if _USE_STRFUNC -int f_putc (TCHAR, FIL*); /* Put a character to the file */ -int f_puts (const TCHAR*, FIL*); /* Put a string to the file */ -int f_printf (FIL*, const TCHAR*, ...); /* Put a formatted string to the file */ -TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */ +int f_putc ( TCHAR, FIL * ); /* Put a character to the file */ +int f_puts ( const TCHAR *, FIL * ); /* Put a string to the file */ +int f_printf ( FIL *, const TCHAR *, ... ); /* Put a formatted string to the file */ +TCHAR *f_gets ( TCHAR *, int, FIL * ); /* Get a string from the file */ #ifndef EOF #define EOF (-1) #endif @@ -457,25 +464,25 @@ TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */ /* RTC function */ #if !_FS_READONLY -DWORD get_fattime (void); +DWORD get_fattime ( void ); #endif /* Unicode support functions */ -#if _USE_LFN /* Unicode - OEM code conversion */ -WCHAR ff_convert (WCHAR, UINT); /* OEM-Unicode bidirectional conversion */ -WCHAR ff_wtoupper (WCHAR); /* Unicode upper-case conversion */ -#if _USE_LFN == 3 /* Memory functions */ -void* ff_memalloc (UINT); /* Allocate memory block */ -void ff_memfree (void*); /* Free memory block */ +#if _USE_LFN /* Unicode - OEM code conversion */ +WCHAR ff_convert ( WCHAR, UINT ); /* OEM-Unicode bidirectional conversion */ +WCHAR ff_wtoupper ( WCHAR ); /* Unicode upper-case conversion */ +#if _USE_LFN == 3 /* Memory functions */ +void *ff_memalloc ( UINT ); /* Allocate memory block */ +void ff_memfree ( void * ); /* Free memory block */ #endif #endif /* Sync functions */ #if _FS_REENTRANT -int ff_cre_syncobj (BYTE, _SYNC_t*);/* Create a sync object */ -int ff_del_syncobj (_SYNC_t); /* Delete a sync object */ -int ff_req_grant (_SYNC_t); /* Lock sync object */ -void ff_rel_grant (_SYNC_t); /* Unlock sync object */ +int ff_cre_syncobj ( BYTE, _SYNC_t * ); /* Create a sync object */ +int ff_del_syncobj ( _SYNC_t ); /* Delete a sync object */ +int ff_req_grant ( _SYNC_t ); /* Lock sync object */ +void ff_rel_grant ( _SYNC_t ); /* Unlock sync object */ #endif @@ -487,56 +494,56 @@ void ff_rel_grant (_SYNC_t); /* Unlock sync object */ /* File access control and file status flags (FIL.flag) */ -#define FA_READ 0x01 -#define FA_OPEN_EXISTING 0x00 -#define FA__ERROR 0x80 +#define FA_READ 0x01 +#define FA_OPEN_EXISTING 0x00 +#define FA__ERROR 0x80 #if !_FS_READONLY -#define FA_WRITE 0x02 -#define FA_CREATE_NEW 0x04 -#define FA_CREATE_ALWAYS 0x08 -#define FA_OPEN_ALWAYS 0x10 -#define FA__WRITTEN 0x20 -#define FA__DIRTY 0x40 +#define FA_WRITE 0x02 +#define FA_CREATE_NEW 0x04 +#define FA_CREATE_ALWAYS 0x08 +#define FA_OPEN_ALWAYS 0x10 +#define FA__WRITTEN 0x20 +#define FA__DIRTY 0x40 #endif /* FAT sub type (FATFS.fs_type) */ -#define FS_FAT12 1 -#define FS_FAT16 2 -#define FS_FAT32 3 +#define FS_FAT12 1 +#define FS_FAT16 2 +#define FS_FAT32 3 /* File attribute bits for directory entry */ -#define AM_RDO 0x01 /* Read only */ -#define AM_HID 0x02 /* Hidden */ -#define AM_SYS 0x04 /* System */ -#define AM_VOL 0x08 /* Volume label */ -#define AM_LFN 0x0F /* LFN entry */ -#define AM_DIR 0x10 /* Directory */ -#define AM_ARC 0x20 /* Archive */ -#define AM_MASK 0x3F /* Mask of defined bits */ +#define AM_RDO 0x01 /* Read only */ +#define AM_HID 0x02 /* Hidden */ +#define AM_SYS 0x04 /* System */ +#define AM_VOL 0x08 /* Volume label */ +#define AM_LFN 0x0F /* LFN entry */ +#define AM_DIR 0x10 /* Directory */ +#define AM_ARC 0x20 /* Archive */ +#define AM_MASK 0x3F /* Mask of defined bits */ /* Fast seek function */ -#define CREATE_LINKMAP 0xFFFFFFFF +#define CREATE_LINKMAP 0xFFFFFFFF /*--------------------------------*/ /* Multi-byte word access macros */ -#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */ -#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr)) -#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr)) -#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val) -#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val) -#else /* Use byte-by-byte access to the FAT structure */ -#define LD_WORD(ptr) (WORD)(((WORD)*(BYTE*)((ptr)+1)<<8)|(WORD)*(BYTE*)(ptr)) -#define LD_DWORD(ptr) (DWORD)(((DWORD)*(BYTE*)((ptr)+3)<<24)|((DWORD)*(BYTE*)((ptr)+2)<<16)|((WORD)*(BYTE*)((ptr)+1)<<8)|*(BYTE*)(ptr)) -#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8) -#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24) +#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */ +#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr)) +#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr)) +#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val) +#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val) +#else /* Use byte-by-byte access to the FAT structure */ +#define LD_WORD(ptr) (WORD)(((WORD)*(BYTE*)((ptr)+1)<<8)|(WORD)*(BYTE*)(ptr)) +#define LD_DWORD(ptr) (DWORD)(((DWORD)*(BYTE*)((ptr)+3)<<24)|((DWORD)*(BYTE*)((ptr)+2)<<16)|((WORD)*(BYTE*)((ptr)+1)<<8)|*(BYTE*)(ptr)) +#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8) +#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24) #endif #ifdef __cplusplus diff --git a/src/bootldr/ffconf.h b/src/bootldr/ffconf.h index 37e3c2f..3ef5d84 100644 --- a/src/bootldr/ffconf.h +++ b/src/bootldr/ffconf.h @@ -7,26 +7,26 @@ / /----------------------------------------------------------------------------*/ #ifndef _FFCONF -#define _FFCONF 8255 /* Revision ID */ +#define _FFCONF 8255 /* Revision ID */ /*---------------------------------------------------------------------------/ / Function and Buffer Configurations /----------------------------------------------------------------------------*/ -#define _FS_TINY 1 /* 0:Normal or 1:Tiny */ +#define _FS_TINY 1 /* 0:Normal or 1:Tiny */ /* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system / object instead of the sector buffer in the individual file object for file / data transfer. This reduces memory consumption 512 bytes each file object. */ -#define _FS_READONLY 1 /* 0:Read/Write or 1:Read only */ +#define _FS_READONLY 1 /* 0:Read/Write or 1:Read only */ /* Setting _FS_READONLY to 1 defines read only configuration. This removes / writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename, / f_truncate and useless f_getfree. */ -#define _FS_MINIMIZE 3 /* 0 to 3 */ +#define _FS_MINIMIZE 3 /* 0 to 3 */ /* The _FS_MINIMIZE option defines minimization level to remove some functions. / / 0: Full function. @@ -36,19 +36,19 @@ / 3: f_lseek is removed in addition to 2. */ -#define _USE_STRFUNC 0 /* 0:Disable or 1/2:Enable */ +#define _USE_STRFUNC 0 /* 0:Disable or 1/2:Enable */ /* To enable string functions, set _USE_STRFUNC to 1 or 2. */ -#define _USE_MKFS 0 /* 0:Disable or 1:Enable */ +#define _USE_MKFS 0 /* 0:Disable or 1:Enable */ /* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */ -#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */ +#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */ /* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */ -#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */ +#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */ /* To enable fast seek feature, set _USE_FASTSEEK to 1. */ @@ -57,7 +57,7 @@ / Locale and Namespace Configurations /----------------------------------------------------------------------------*/ -#define _CODE_PAGE 1 +#define _CODE_PAGE 1 /* The _CODE_PAGE specifies the OEM code page to be used on the target system. / Incorrect setting of the code page can cause a file open failure. / @@ -86,12 +86,12 @@ / 857 - Turkish (OEM) / 862 - Hebrew (OEM) / 874 - Thai (OEM, Windows) -/ 1 - ASCII only (Valid for non LFN cfg.) +/ 1 - ASCII only (Valid for non LFN cfg.) */ -#define _USE_LFN 0 /* 0 to 3 */ -#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */ +#define _USE_LFN 0 /* 0 to 3 */ +#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */ /* The _USE_LFN option switches the LFN support. / / 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect. @@ -105,12 +105,12 @@ / ff_memalloc() and ff_memfree() must be added to the project. */ -#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */ +#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */ /* To switch the character code set on FatFs API to Unicode, / enable LFN feature and set _LFN_UNICODE to 1. */ -#define _FS_RPATH 0 /* 0 to 2 */ +#define _FS_RPATH 0 /* 0 to 2 */ /* The _FS_RPATH option configures relative path feature. / / 0: Disable relative path feature and remove related functions. @@ -125,11 +125,11 @@ / Physical Drive Configurations /----------------------------------------------------------------------------*/ -#define _VOLUMES 1 +#define _VOLUMES 1 /* Number of volumes (logical drives) to be used. */ -#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */ +#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */ /* Maximum sector size to be handled. / Always set 512 for memory card and hard disk but a larger value may be / required for floppy disk (512/1024) and optical disk (512/2048). @@ -137,13 +137,13 @@ / to the disk_ioctl function. */ -#define _MULTI_PARTITION 0 /* 0:Single partition or 1:Multiple partition */ +#define _MULTI_PARTITION 0 /* 0:Single partition or 1:Multiple partition */ /* When set to 0, each volume is bound to the same physical drive number and / it can mount only first primaly partition. When it is set to 1, each volume / is tied to the partitions listed in VolToPart[]. */ -#define _USE_ERASE 0 /* 0:Disable or 1:Enable */ +#define _USE_ERASE 0 /* 0:Disable or 1:Enable */ /* To enable sector erase feature, set _USE_ERASE to 1. */ @@ -152,7 +152,7 @@ / System Configurations /----------------------------------------------------------------------------*/ -#define _WORD_ACCESS 0 /* 0 or 1 */ +#define _WORD_ACCESS 0 /* 0 or 1 */ /* Set 0 first and it is always compatible with all platforms. The _WORD_ACCESS / option defines which access method is used to the word data on the FAT volume. / @@ -168,9 +168,9 @@ /* Include a header file here to define sync object types on the O/S */ /* #include , , or ohters. */ -#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */ -#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */ -#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */ +#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */ +#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */ +#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */ /* The _FS_REENTRANT option switches the reentrancy of the FatFs module. / @@ -180,7 +180,7 @@ / function must be added to the project. */ -#define _FS_SHARE 0 /* 0:Disable or >=1:Enable */ +#define _FS_SHARE 0 /* 0:Disable or >=1:Enable */ /* To enable file shareing feature, set _FS_SHARE to 1 or greater. The value defines how many files can be opened simultaneously. */ diff --git a/src/bootldr/fileops.c b/src/bootldr/fileops.c index bc8853d..789fbe0 100644 --- a/src/bootldr/fileops.c +++ b/src/bootldr/fileops.c @@ -12,39 +12,47 @@ WCHAR ff_convert(WCHAR w, UINT dir) { int newcard; -void file_init() { - file_res=f_mount(0, &fatfs); - newcard = 0; +void file_init() +{ + file_res = f_mount( 0, &fatfs ); + newcard = 0; } -void file_reinit(void) { - disk_init(); - file_init(); +void file_reinit( void ) +{ + disk_init(); + file_init(); } -void file_open_by_filinfo(FILINFO* fno) { - file_res = l_openfilebycluster(&fatfs, &file_handle, (TCHAR*)"", fno->clust, fno->fsize); +void file_open_by_filinfo( FILINFO *fno ) +{ + file_res = l_openfilebycluster( &fatfs, &file_handle, ( TCHAR * )"", fno->clust, fno->fsize ); } -void file_open(uint8_t* filename, BYTE flags) { - if (disk_state == DISK_CHANGED) { - file_reinit(); - newcard = 1; - } - file_res = f_open(&file_handle, (TCHAR*)filename, flags); - file_block_off = sizeof(file_buf); - file_block_max = sizeof(file_buf); - file_status = file_res ? FILE_ERR : FILE_OK; +void file_open( uint8_t *filename, BYTE flags ) +{ + if ( disk_state == DISK_CHANGED ) + { + file_reinit(); + newcard = 1; + } + + file_res = f_open( &file_handle, ( TCHAR * )filename, flags ); + file_block_off = sizeof( file_buf ); + file_block_max = sizeof( file_buf ); + file_status = file_res ? FILE_ERR : FILE_OK; } -void file_close() { - file_res = f_close(&file_handle); +void file_close() +{ + file_res = f_close( &file_handle ); } -UINT file_read() { - UINT bytes_read; - file_res = f_read(&file_handle, file_buf, sizeof(file_buf), &bytes_read); - return bytes_read; +UINT file_read() +{ + UINT bytes_read; + file_res = f_read( &file_handle, file_buf, sizeof( file_buf ), &bytes_read ); + return bytes_read; } /*UINT file_write() { @@ -56,14 +64,18 @@ UINT file_read() { return bytes_written; }*/ -UINT file_readblock(void* buf, uint32_t addr, uint16_t size) { - UINT bytes_read; - file_res = f_lseek(&file_handle, addr); - if(file_handle.fptr != addr) { - return 0; - } - file_res = f_read(&file_handle, buf, size, &bytes_read); - return bytes_read; +UINT file_readblock( void *buf, uint32_t addr, uint16_t size ) +{ + UINT bytes_read; + file_res = f_lseek( &file_handle, addr ); + + if ( file_handle.fptr != addr ) + { + return 0; + } + + file_res = f_read( &file_handle, buf, size, &bytes_read ); + return bytes_read; } /*UINT file_writeblock(void* buf, uint32_t addr, uint16_t size) { @@ -74,11 +86,19 @@ UINT file_readblock(void* buf, uint32_t addr, uint16_t size) { return bytes_written; }*/ -uint8_t file_getc() { - if(file_block_off == file_block_max) { - file_block_max = file_read(); - if(file_block_max == 0) file_status = FILE_EOF; - file_block_off = 0; - } - return file_buf[file_block_off++]; +uint8_t file_getc() +{ + if ( file_block_off == file_block_max ) + { + file_block_max = file_read(); + + if ( file_block_max == 0 ) + { + file_status = FILE_EOF; + } + + file_block_off = 0; + } + + return file_buf[file_block_off++]; } diff --git a/src/bootldr/fileops.h b/src/bootldr/fileops.h index a471c09..dc79289 100644 --- a/src/bootldr/fileops.h +++ b/src/bootldr/fileops.h @@ -29,25 +29,25 @@ #include #include "ff.h" -enum filestates { FILE_OK=0, FILE_ERR, FILE_EOF }; +enum filestates { FILE_OK = 0, FILE_ERR, FILE_EOF }; #define GCC_ALIGN_WORKAROUND __attribute__ ((aligned(4))) -BYTE file_buf[512] GCC_ALIGN_WORKAROUND; -FATFS fatfs; -FIL file_handle; -FRESULT file_res; -uint8_t file_lfn[258]; -uint16_t file_block_off, file_block_max; -enum filestates file_status; +extern BYTE file_buf[512]; +extern FATFS fatfs; +extern FIL file_handle; +extern FRESULT file_res; +extern uint8_t file_lfn[258]; +extern uint16_t file_block_off, file_block_max; +extern enum filestates file_status; -void file_init(void); -void file_open(uint8_t* filename, BYTE flags); -void file_open_by_filinfo(FILINFO* fno); -void file_close(void); -UINT file_read(void); -UINT file_write(void); -UINT file_readblock(void* buf, uint32_t addr, uint16_t size); -UINT file_writeblock(void* buf, uint32_t addr, uint16_t size); +void file_init( void ); +void file_open( uint8_t *filename, BYTE flags ); +void file_open_by_filinfo( FILINFO *fno ); +void file_close( void ); +UINT file_read( void ); +UINT file_write( void ); +UINT file_readblock( void *buf, uint32_t addr, uint16_t size ); +UINT file_writeblock( void *buf, uint32_t addr, uint16_t size ); -uint8_t file_getc(void); +uint8_t file_getc( void ); #endif diff --git a/src/bootldr/iap.c b/src/bootldr/iap.c index f1135e8..14a709b 100644 --- a/src/bootldr/iap.c +++ b/src/bootldr/iap.c @@ -12,197 +12,284 @@ uint32_t iap_cmd[5]; uint32_t iap_res[5]; uint32_t flash_sig[4]; -IAP iap_entry = (IAP) IAP_LOCATION; +IAP iap_entry = ( IAP ) IAP_LOCATION; -uint32_t calc_flash_crc(uint32_t start, uint32_t len) { - DBG_BL printf("calc_flash_crc(%08lx, %08lx) {\n", start, len); - uint32_t end = start + len; - if(end > 0x20000) { - len = 0x1ffff - start; - end = 0x20000; - } - uint32_t crc = 0xffffffff; - uint32_t s = start; - while(s < end) { - crc = crc32_update(crc, *(const unsigned char*)(s)); - s++; - } - crc = crc_finalize(crc); - DBG_BL printf(" crc generated. result=%08lx\n", crc); - DBG_BL printf("} //calc_flash_crc\n"); - return crc; -} +uint32_t calc_flash_crc( uint32_t start, uint32_t len ) +{ + DBG_BL printf( "calc_flash_crc(%08lx, %08lx) {\n", start, len ); + uint32_t end = start + len; -void test_iap() { - iap_cmd[0]=54; - iap_entry(iap_cmd, iap_res); - DBG_BL printf("Part ID=%08lx\n", iap_res[1]); -} - -void print_header(sd2snes_fw_header *header) { - DBG_BL printf(" magic = %08lx\n version = %08lx\n size = %08lx\n crc = %08lx\n ~crc = %08lx\n", - header->magic, header->version, header->size, - header->crc, header->crcc); -} - -int check_header(sd2snes_fw_header *header, uint32_t crc) { - if((header->magic != FW_MAGIC) - || (header->size < 0x200) - || (header->size > (0x1ffff - FW_START)) - || ((header->crc ^ header->crcc) != 0xffffffff)) { - return ERR_FLASHHD; - } - if(header->crc != crc) { - return ERR_FLASHCRC; - } - return ERR_OK; -} - -FLASH_RES check_flash() { - sd2snes_fw_header *fw_header = (sd2snes_fw_header*) FW_START; - uint32_t flash_addr = FW_START; - if(flash_addr != FW_START) { - DBG_BL printf("address sanity check failed. expected 0x%08lx, got 0x%08lx.\nSomething is terribly wrong.\nBailing out to avoid bootldr self-corruption.\n", FW_START, flash_addr); - return ERR_HW; - } - DBG_BL printf("Current flash contents:\n"); - DBG_BL print_header(fw_header); - uint32_t crc = calc_flash_crc(flash_addr + 0x100, (fw_header->size & 0x1ffff)); - return check_header(fw_header, crc); -} - -IAP_RES iap_wrap(uint32_t *iap_cmd, uint32_t *iap_res) { -// NVIC_DisableIRQ(RIT_IRQn); -// NVIC_DisableIRQ(UART_IRQ); - for(volatile int i=0; i<2048; i++); - iap_entry(iap_cmd, iap_res); - for(volatile int i=0; i<2048; i++); -// NVIC_EnableIRQ(UART_IRQ); - return iap_res[0]; -} - -IAP_RES iap_prepare_for_write(uint32_t start, uint32_t end) { - if(start < (FW_START / 0x1000)) return INVALID_SECTOR; - iap_cmd[0] = 50; - iap_cmd[1] = start; - iap_cmd[2] = end; - iap_wrap(iap_cmd, iap_res); - return iap_res[0]; -} - -IAP_RES iap_erase(uint32_t start, uint32_t end) { - if(start < (FW_START / 0x1000)) return INVALID_SECTOR; - iap_cmd[0] = 52; - iap_cmd[1] = start; - iap_cmd[2] = end; - iap_cmd[3] = CONFIG_CPU_FREQUENCY / 1000L; - iap_wrap(iap_cmd, iap_res); - return iap_res[0]; -} - -IAP_RES iap_ram2flash(uint32_t tgt, uint8_t *src, int num) { - iap_cmd[0] = 51; - iap_cmd[1] = tgt; - iap_cmd[2] = (uint32_t)src; - iap_cmd[3] = num; - iap_cmd[4] = CONFIG_CPU_FREQUENCY / 1000L; - iap_wrap(iap_cmd, iap_res); - return iap_res[0]; -} - -FLASH_RES flash_file(uint8_t *filename) { - sd2snes_fw_header *fw_header = (sd2snes_fw_header*) FW_START; - uint32_t flash_addr = FW_START; - uint32_t file_crc = 0xffffffff; - uint16_t count; - sd2snes_fw_header file_header; - UINT bytes_read; - if(flash_addr != FW_START) { - DBG_BL printf("address sanity check failed. expected 0x%08lx, got 0x%08lx.\nSomething is terribly wrong.\nBailing out to avoid bootldr self-corruption.\n", FW_START, flash_addr); - return ERR_HW; - } - file_open(filename, FA_READ); - if(file_res) { - DBG_BL printf("file_open: error %d\n", file_res); - return ERR_FS; - } - DBG_BL printf("firmware image found. file size: %ld\n", file_handle.fsize); - DBG_BL printf("reading header...\n"); - f_read(&file_handle, &file_header, 32, &bytes_read); - DBG_BL print_header(&file_header); - if(check_flash() || file_header.version != fw_header->version || file_header.version == FW_MAGIC || fw_header->version == FW_MAGIC) { - DBG_UART uart_putc('F'); - f_read(&file_handle, file_buf, 0xe0, &bytes_read); - for(;;) { - bytes_read = file_read(); - if(file_res || !bytes_read) break; - for(count = 0; count < bytes_read; count++) { - file_crc = crc32_update(file_crc, file_buf[count]); - } - } - file_crc = crc_finalize(file_crc); - DBG_BL printf("file crc=%08lx\n", file_crc); - if(check_header(&file_header, file_header.crc) != ERR_OK) { - DBG_BL printf("Invalid firmware file (header corrupted).\n"); - return ERR_FILEHD; - } - if(file_header.crc != file_crc) { - DBG_BL printf("Firmware file checksum error.\n"); - return ERR_FILECHK; + if ( end > 0x20000 ) + { + len = 0x1ffff - start; + end = 0x20000; } - uint32_t res; + uint32_t crc = 0xffffffff; + uint32_t s = start; - writeled(1); - DBG_BL printf("erasing flash...\n"); - DBG_UART uart_putc('P'); - if((res = iap_prepare_for_write(FW_START / 0x1000, FLASH_SECTORS)) != CMD_SUCCESS) { - DBG_BL printf("error %ld while preparing for erase\n", res); - DBG_UART uart_putc('X'); - return ERR_FLASHPREP; - }; - DBG_UART uart_putc('E'); - if((res = iap_erase(FW_START / 0x1000, FLASH_SECTORS)) != CMD_SUCCESS) { - DBG_BL printf("error %ld while erasing\n", res); - DBG_UART uart_putc('X'); - return ERR_FLASHERASE; + while ( s < end ) + { + crc = crc32_update( crc, *( const unsigned char * )( s ) ); + s++; } - DBG_BL printf("writing... @%08lx\n", flash_addr); - file_close(); - file_open(filename, FA_READ); - uint8_t current_sec; - uint32_t total_read = 0; - for(flash_addr = FW_START; flash_addr < 0x00020000; flash_addr += 0x200) { - total_read += (bytes_read = file_read()); - if(file_res || !bytes_read) break; - current_sec = flash_addr & 0x10000 ? (16 + ((flash_addr >> 15) & 1)) - : (flash_addr >> 12); - DBG_BL printf("current_sec=%d flash_addr=%08lx\n", current_sec, flash_addr); - DBG_UART uart_putc('.'); - if(current_sec < (FW_START / 0x1000)) return ERR_FLASH; - DBG_UART uart_putc(current_sec["0123456789ABCDEFGH"]); - DBG_UART uart_putc('p'); - if((res = iap_prepare_for_write(current_sec, current_sec)) != CMD_SUCCESS) { - DBG_BL printf("error %ld while preparing sector %d for write\n", res, current_sec); - DBG_UART uart_putc('X'); - return ERR_FLASH; - } - DBG_UART uart_putc('w'); - if((res = iap_ram2flash(flash_addr, file_buf, 512)) != CMD_SUCCESS) { - //printf("error %ld while writing to address %08lx (sector %d)\n", res, flash_addr, current_sec); - DBG_UART uart_putc('X'); - return ERR_FLASH; - } - } - if(total_read != (file_header.size + 0x100)) { - DBG_BL printf("wrote less data than expected! (%08lx vs. %08lx)\n", total_read, file_header.size); -// DBG_UART uart_putc('X'); - return ERR_FILECHK; - } - writeled(0); - } else { - DBG_UART uart_putc('n'); - DBG_BL printf("flash content is ok, no version mismatch, no forced upgrade. No need to flash\n"); - } - return ERR_OK; + + crc = crc_finalize( crc ); + DBG_BL printf( " crc generated. result=%08lx\n", crc ); + DBG_BL printf( "} //calc_flash_crc\n" ); + return crc; +} + +void test_iap() +{ + iap_cmd[0] = 54; + iap_entry( iap_cmd, iap_res ); + DBG_BL printf( "Part ID=%08lx\n", iap_res[1] ); +} + +void print_header( sd2snes_fw_header *header ) +{ + DBG_BL printf( " magic = %08lx\n version = %08lx\n size = %08lx\n crc = %08lx\n ~crc = %08lx\n", + header->magic, header->version, header->size, + header->crc, header->crcc ); +} + +int check_header( sd2snes_fw_header *header, uint32_t crc ) +{ + if ( ( header->magic != FW_MAGIC ) + || ( header->size < 0x200 ) + || ( header->size > ( 0x1ffff - FW_START ) ) + || ( ( header->crc ^ header->crcc ) != 0xffffffff ) ) + { + return ERR_FLASHHD; + } + + if ( header->crc != crc ) + { + return ERR_FLASHCRC; + } + + return ERR_OK; +} + +FLASH_RES check_flash() +{ + sd2snes_fw_header *fw_header = ( sd2snes_fw_header * ) FW_START; + uint32_t flash_addr = FW_START; + + if ( flash_addr != FW_START ) + { + DBG_BL printf( "address sanity check failed. expected 0x%08lx, got 0x%08lx.\nSomething is terribly wrong.\nBailing out to avoid bootldr self-corruption.\n", + FW_START, flash_addr ); + return ERR_HW; + } + + DBG_BL printf( "Current flash contents:\n" ); + DBG_BL print_header( fw_header ); + uint32_t crc = calc_flash_crc( flash_addr + 0x100, ( fw_header->size & 0x1ffff ) ); + return check_header( fw_header, crc ); +} + +IAP_RES iap_wrap( uint32_t *iap_cmd, uint32_t *iap_res ) +{ + // NVIC_DisableIRQ(RIT_IRQn); + // NVIC_DisableIRQ(UART_IRQ); + for ( volatile int i = 0; i < 2048; i++ ); + + iap_entry( iap_cmd, iap_res ); + + for ( volatile int i = 0; i < 2048; i++ ); + + // NVIC_EnableIRQ(UART_IRQ); + return iap_res[0]; +} + +IAP_RES iap_prepare_for_write( uint32_t start, uint32_t end ) +{ + if ( start < ( FW_START / 0x1000 ) ) + { + return INVALID_SECTOR; + } + + iap_cmd[0] = 50; + iap_cmd[1] = start; + iap_cmd[2] = end; + iap_wrap( iap_cmd, iap_res ); + return iap_res[0]; +} + +IAP_RES iap_erase( uint32_t start, uint32_t end ) +{ + if ( start < ( FW_START / 0x1000 ) ) + { + return INVALID_SECTOR; + } + + iap_cmd[0] = 52; + iap_cmd[1] = start; + iap_cmd[2] = end; + iap_cmd[3] = CONFIG_CPU_FREQUENCY / 1000L; + iap_wrap( iap_cmd, iap_res ); + return iap_res[0]; +} + +IAP_RES iap_ram2flash( uint32_t tgt, uint8_t *src, int num ) +{ + iap_cmd[0] = 51; + iap_cmd[1] = tgt; + iap_cmd[2] = ( uint32_t )src; + iap_cmd[3] = num; + iap_cmd[4] = CONFIG_CPU_FREQUENCY / 1000L; + iap_wrap( iap_cmd, iap_res ); + return iap_res[0]; +} + +FLASH_RES flash_file( uint8_t *filename ) +{ + sd2snes_fw_header *fw_header = ( sd2snes_fw_header * ) FW_START; + uint32_t flash_addr = FW_START; + uint32_t file_crc = 0xffffffff; + uint16_t count; + sd2snes_fw_header file_header; + UINT bytes_read; + + if ( flash_addr != FW_START ) + { + DBG_BL printf( "address sanity check failed. expected 0x%08lx, got 0x%08lx.\nSomething is terribly wrong.\nBailing out to avoid bootldr self-corruption.\n", + FW_START, flash_addr ); + return ERR_HW; + } + + file_open( filename, FA_READ ); + + if ( file_res ) + { + DBG_BL printf( "file_open: error %d\n", file_res ); + return ERR_FS; + } + + DBG_BL printf( "firmware image found. file size: %ld\n", file_handle.fsize ); + DBG_BL printf( "reading header...\n" ); + f_read( &file_handle, &file_header, 32, &bytes_read ); + DBG_BL print_header( &file_header ); + + if ( check_flash() || file_header.version != fw_header->version || file_header.version == FW_MAGIC + || fw_header->version == FW_MAGIC ) + { + DBG_UART uart_putc( 'F' ); + f_read( &file_handle, file_buf, 0xe0, &bytes_read ); + + for ( ;; ) + { + bytes_read = file_read(); + + if ( file_res || !bytes_read ) + { + break; + } + + for ( count = 0; count < bytes_read; count++ ) + { + file_crc = crc32_update( file_crc, file_buf[count] ); + } + } + + file_crc = crc_finalize( file_crc ); + DBG_BL printf( "file crc=%08lx\n", file_crc ); + + if ( check_header( &file_header, file_header.crc ) != ERR_OK ) + { + DBG_BL printf( "Invalid firmware file (header corrupted).\n" ); + return ERR_FILEHD; + } + + if ( file_header.crc != file_crc ) + { + DBG_BL printf( "Firmware file checksum error.\n" ); + return ERR_FILECHK; + } + + uint32_t res; + + writeled( 1 ); + DBG_BL printf( "erasing flash...\n" ); + DBG_UART uart_putc( 'P' ); + + if ( ( res = iap_prepare_for_write( FW_START / 0x1000, FLASH_SECTORS ) ) != CMD_SUCCESS ) + { + DBG_BL printf( "error %ld while preparing for erase\n", res ); + DBG_UART uart_putc( 'X' ); + return ERR_FLASHPREP; + }; + + DBG_UART uart_putc( 'E' ); + + if ( ( res = iap_erase( FW_START / 0x1000, FLASH_SECTORS ) ) != CMD_SUCCESS ) + { + DBG_BL printf( "error %ld while erasing\n", res ); + DBG_UART uart_putc( 'X' ); + return ERR_FLASHERASE; + } + + DBG_BL printf( "writing... @%08lx\n", flash_addr ); + file_close(); + file_open( filename, FA_READ ); + uint8_t current_sec; + uint32_t total_read = 0; + + for ( flash_addr = FW_START; flash_addr < 0x00020000; flash_addr += 0x200 ) + { + total_read += ( bytes_read = file_read() ); + + if ( file_res || !bytes_read ) + { + break; + } + + current_sec = flash_addr & 0x10000 ? ( 16 + ( ( flash_addr >> 15 ) & 1 ) ) + : ( flash_addr >> 12 ); + DBG_BL printf( "current_sec=%d flash_addr=%08lx\n", current_sec, flash_addr ); + DBG_UART uart_putc( '.' ); + + if ( current_sec < ( FW_START / 0x1000 ) ) + { + return ERR_FLASH; + } + + DBG_UART uart_putc( current_sec["0123456789ABCDEFGH"] ); + DBG_UART uart_putc( 'p' ); + + if ( ( res = iap_prepare_for_write( current_sec, current_sec ) ) != CMD_SUCCESS ) + { + DBG_BL printf( "error %ld while preparing sector %d for write\n", res, current_sec ); + DBG_UART uart_putc( 'X' ); + return ERR_FLASH; + } + + DBG_UART uart_putc( 'w' ); + + if ( ( res = iap_ram2flash( flash_addr, file_buf, 512 ) ) != CMD_SUCCESS ) + { + //printf("error %ld while writing to address %08lx (sector %d)\n", res, flash_addr, current_sec); + DBG_UART uart_putc( 'X' ); + return ERR_FLASH; + } + } + + if ( total_read != ( file_header.size + 0x100 ) ) + { + DBG_BL printf( "wrote less data than expected! (%08lx vs. %08lx)\n", total_read, file_header.size ); + // DBG_UART uart_putc('X'); + return ERR_FILECHK; + } + + writeled( 0 ); + } + else + { + DBG_UART uart_putc( 'n' ); + DBG_BL printf( "flash content is ok, no version mismatch, no forced upgrade. No need to flash\n" ); + } + + return ERR_OK; } diff --git a/src/bootldr/iap.h b/src/bootldr/iap.h index 47ec88e..ae09486 100644 --- a/src/bootldr/iap.h +++ b/src/bootldr/iap.h @@ -2,39 +2,41 @@ #define IAP_H #define IAP_LOCATION 0x1fff1ff1 -typedef void (*IAP)(uint32_t*, uint32_t*); +typedef void ( *IAP )( uint32_t *, uint32_t * ); typedef enum {ERR_OK = 0, ERR_HW, ERR_FS, ERR_FILEHD, ERR_FILECHK, ERR_FLASHHD, ERR_FLASHCRC, ERR_FLASHPREP, ERR_FLASHERASE, ERR_FLASH} FLASH_RES; -typedef enum { -/* 0*/ CMD_SUCCESS = 0, -/* 1*/ INVALID_COMMAND, -/* 2*/ SRC_ADDR_ERROR, -/* 3*/ DST_ADDR_ERROR, -/* 4*/ SRC_ADDR_NOT_MAPPED, -/* 5*/ DST_ADDR_NOT_MAPPED, -/* 6*/ COUNT_ERROR, -/* 7*/ INVALID_SECTOR, -/* 8*/ SECTOR_NOT_BLANK, -/* 9*/ SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION, -/*10*/ COMPARE_ERROR, -/*11*/ BUSY +typedef enum +{ + /* 0*/ CMD_SUCCESS = 0, + /* 1*/ INVALID_COMMAND, + /* 2*/ SRC_ADDR_ERROR, + /* 3*/ DST_ADDR_ERROR, + /* 4*/ SRC_ADDR_NOT_MAPPED, + /* 5*/ DST_ADDR_NOT_MAPPED, + /* 6*/ COUNT_ERROR, + /* 7*/ INVALID_SECTOR, + /* 8*/ SECTOR_NOT_BLANK, + /* 9*/ SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION, + /*10*/ COMPARE_ERROR, + /*11*/ BUSY } IAP_RES; #define FW_MAGIC (0x44534E53) -typedef struct { - uint32_t magic; - uint32_t version; - uint32_t size; - uint32_t crc; - uint32_t crcc; +typedef struct +{ + uint32_t magic; + uint32_t version; + uint32_t size; + uint32_t crc; + uint32_t crcc; } sd2snes_fw_header; -uint32_t calc_flash_crc(uint32_t start, uint32_t end); -void test_iap(void); -FLASH_RES check_flash(void); -FLASH_RES flash_file(uint8_t* filename); +uint32_t calc_flash_crc( uint32_t start, uint32_t end ); +void test_iap( void ); +FLASH_RES check_flash( void ); +FLASH_RES flash_file( uint8_t *filename ); #endif diff --git a/src/bootldr/integer.h b/src/bootldr/integer.h index ccc97d3..76c1683 100644 --- a/src/bootldr/integer.h +++ b/src/bootldr/integer.h @@ -5,7 +5,7 @@ #ifndef _INTEGER #define _INTEGER -#ifdef _WIN32 /* FatFs development platform */ +#ifdef _WIN32 /* FatFs development platform */ #include #include diff --git a/src/bootldr/led.c b/src/bootldr/led.c index a6dc01a..5357b02 100644 --- a/src/bootldr/led.c +++ b/src/bootldr/led.c @@ -18,73 +18,85 @@ int led_writeledstate = 0; write red P1.23 PWM1[4] */ -void rdyled(unsigned int state) { - BITBAND(LPC_GPIO2->FIODIR, 4) = state; - led_rdyledstate = state; +void rdyled( unsigned int state ) +{ + BITBANG( LPC_GPIO2->FIODIR, 4 ) = state; + led_rdyledstate = state; } -void readled(unsigned int state) { - BITBAND(LPC_GPIO2->FIODIR, 5) = state; - led_readledstate = state; +void readled( unsigned int state ) +{ + BITBANG( LPC_GPIO2->FIODIR, 5 ) = state; + led_readledstate = state; } -void writeled(unsigned int state) { - BITBAND(LPC_GPIO1->FIODIR, 23) = state; - led_writeledstate = state; +void writeled( unsigned int state ) +{ + BITBANG( LPC_GPIO1->FIODIR, 23 ) = state; + led_writeledstate = state; } -void led_clkout32(uint32_t val) { - while(1) { - rdyled(1); - delay_ms(400); - readled((val & BV(31))>>31); - rdyled(0); - val<<=1; - delay_ms(400); - } +void led_clkout32( uint32_t val ) +{ + while ( 1 ) + { + rdyled( 1 ); + delay_ms( 400 ); + readled( ( val & BV( 31 ) ) >> 31 ); + rdyled( 0 ); + val <<= 1; + delay_ms( 400 ); + } } -void toggle_rdy_led() { - rdyled(~led_rdyledstate); +void toggle_rdy_led() +{ + rdyled( ~led_rdyledstate ); } -void toggle_read_led() { - readled(~led_readledstate); +void toggle_read_led() +{ + readled( ~led_readledstate ); } -void toggle_write_led() { - writeled(~led_writeledstate); +void toggle_write_led() +{ + writeled( ~led_writeledstate ); } -void led_panic() { - while(1) { - LPC_GPIO2->FIODIR |= BV(4) | BV(5); - LPC_GPIO1->FIODIR |= BV(23); - delay_ms(350); - LPC_GPIO2->FIODIR &= ~(BV(4) | BV(5)); - LPC_GPIO1->FIODIR &= ~BV(23); - delay_ms(350); - } +void led_panic() +{ + while ( 1 ) + { + LPC_GPIO2->FIODIR |= BV( 4 ) | BV( 5 ); + LPC_GPIO1->FIODIR |= BV( 23 ); + delay_ms( 350 ); + LPC_GPIO2->FIODIR &= ~( BV( 4 ) | BV( 5 ) ); + LPC_GPIO1->FIODIR &= ~BV( 23 ); + delay_ms( 350 ); + } } -void led_std() { - BITBAND(LPC_PINCON->PINSEL4, 9) = 0; - BITBAND(LPC_PINCON->PINSEL4, 8) = 0; +void led_std() +{ + BITBANG( LPC_PINCON->PINSEL4, 9 ) = 0; + BITBANG( LPC_PINCON->PINSEL4, 8 ) = 0; - BITBAND(LPC_PINCON->PINSEL4, 11) = 0; - BITBAND(LPC_PINCON->PINSEL4, 10) = 0; + BITBANG( LPC_PINCON->PINSEL4, 11 ) = 0; + BITBANG( LPC_PINCON->PINSEL4, 10 ) = 0; - BITBAND(LPC_PINCON->PINSEL3, 15) = 0; - BITBAND(LPC_PINCON->PINSEL3, 14) = 0; + BITBANG( LPC_PINCON->PINSEL3, 15 ) = 0; + BITBANG( LPC_PINCON->PINSEL3, 14 ) = 0; - BITBAND(LPC_PWM1->PCR, 12) = 0; - BITBAND(LPC_PWM1->PCR, 13) = 0; - BITBAND(LPC_PWM1->PCR, 14) = 0; + BITBANG( LPC_PWM1->PCR, 12 ) = 0; + BITBANG( LPC_PWM1->PCR, 13 ) = 0; + BITBANG( LPC_PWM1->PCR, 14 ) = 0; } -void led_init() { -/* power is already connected by default */ -/* set PCLK divider to 8 */ - BITBAND(LPC_SC->PCLKSEL1, 21) = 1; - BITBAND(LPC_SC->PCLKSEL1, 20) = 1; +void led_init() +{ + /* power is already connected by default */ + /* set PCLK divider to 8 */ + BITBANG( LPC_SC->PCLKSEL1, 21 ) = 1; + BITBANG( LPC_SC->PCLKSEL1, 20 ) = 1; } diff --git a/src/bootldr/led.h b/src/bootldr/led.h index ce97426..9a44f16 100644 --- a/src/bootldr/led.h +++ b/src/bootldr/led.h @@ -3,15 +3,15 @@ #ifndef _LED_H #define _LED_H -void readled(unsigned int state); -void writeled(unsigned int state); -void rdyled(unsigned int state); -void led_clkout32(uint32_t val); -void toggle_rdy_led(void); -void toggle_read_led(void); -void toggle_write_led(void); -void led_panic(void); -void led_std(void); -void led_init(void); +void readled( unsigned int state ); +void writeled( unsigned int state ); +void rdyled( unsigned int state ); +void led_clkout32( uint32_t val ); +void toggle_rdy_led( void ); +void toggle_read_led( void ); +void toggle_write_led( void ); +void led_panic( void ); +void led_std( void ); +void led_init( void ); #endif diff --git a/src/bootldr/main.c b/src/bootldr/main.c index 37fa4a7..31dcb31 100644 --- a/src/bootldr/main.c +++ b/src/bootldr/main.c @@ -15,92 +15,118 @@ #include "fileops.h" #include "iap.h" -#define EMC0TOGGLE (3<<4) -#define MR0R (1<<1) +#define EMC0TOGGLE (3<<4) +#define MR0R (1<<1) int i; +BYTE file_buf[512] GCC_ALIGN_WORKAROUND; +FATFS fatfs; +FIL file_handle; +FRESULT file_res; +uint8_t file_lfn[258]; +uint16_t file_block_off, file_block_max; +enum filestates file_status; + volatile enum diskstates disk_state; extern volatile tick_t ticks; -int (*chain)(void); +int ( *chain )( void ); -int main(void) { - SNES_CIC_PAIR_REG->FIODIR = BV(SNES_CIC_PAIR_BIT); - BITBAND(SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT) = 1; -/* LPC_GPIO2->FIODIR = BV(0) | BV(1) | BV(2); */ -// LPC_GPIO0->FIODIR = BV(16); +int main( void ) +{ + SNES_CIC_PAIR_REG->FIODIR = BV( SNES_CIC_PAIR_BIT ); + BITBANG( SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT ) = 1; - /* connect UART3 on P0[25:26] + SSP0 on P0[15:18] + MAT3.0 on P0[10] */ - LPC_PINCON->PINSEL1 = BV(18) | BV(19) | BV(20) | BV(21) /* UART3 */ - | BV(3) | BV(5); /* SSP0 (FPGA) except SS */ - LPC_PINCON->PINSEL0 = BV(31); /* SSP0 */ -/* | BV(13) | BV(15) | BV(17) | BV(19) SSP1 (SD) */ + /* LPC_GPIO2->FIODIR = BV(0) | BV(1) | BV(2); */ + // LPC_GPIO0->FIODIR = BV(16); - /* pull-down CIC data lines */ - LPC_PINCON->PINMODE0 = BV(0) | BV(1) | BV(2) | BV(3); + /* connect UART3 on P0[25:26] + SSP0 on P0[15:18] + MAT3.0 on P0[10] */ + LPC_PINCON->PINSEL1 = BV( 18 ) | BV( 19 ) | BV( 20 ) | BV( 21 ) /* UART3 */ + | BV( 3 ) | BV( 5 ); /* SSP0 (FPGA) except SS */ + LPC_PINCON->PINSEL0 = BV( 31 ); /* SSP0 */ + /* | BV(13) | BV(15) | BV(17) | BV(19) SSP1 (SD) */ - clock_disconnect(); - power_init(); - timer_init(); - DBG_UART uart_init(); - led_init(); - readled(0); - rdyled(1); - writeled(0); - /* do this last because the peripheral init()s change PCLK dividers */ - clock_init(); -// LPC_PINCON->PINSEL0 |= BV(20) | BV(21); /* MAT3.0 (FPGA clock) */ - sdn_init(); + /* pull-down CIC data lines */ + LPC_PINCON->PINMODE0 = BV( 0 ) | BV( 1 ) | BV( 2 ) | BV( 3 ); - for(i = 0; i < 20; i++) uart_putc('-'); - uart_putc('\n'); + clock_disconnect(); + power_init(); + timer_init(); + DBG_UART uart_init(); + led_init(); + readled( 0 ); + rdyled( 1 ); + writeled( 0 ); + /* do this last because the peripheral init()s change PCLK dividers */ + clock_init(); + // LPC_PINCON->PINSEL0 |= BV(20) | BV(21); /* MAT3.0 (FPGA clock) */ + sdn_init(); - DBG_BL printf("chksum=%08lx\n", *(uint32_t*)28); - /*DBG_BL*/ printf("\n\nsd2snes mk.2 bootloader\nver.: " VER "\ncpu clock: %ld Hz\n", CONFIG_CPU_FREQUENCY); -DBG_BL printf("PCONP=%lx\n", LPC_SC->PCONP); -/* setup timer (fpga clk) */ - LPC_TIM3->CTCR=0; - LPC_TIM3->EMR=EMC0TOGGLE; - LPC_TIM3->MCR=MR0R; - LPC_TIM3->MR0=1; - LPC_TIM3->TCR=1; - NVIC->ICER[0] = 0xffffffff; - NVIC->ICER[1] = 0xffffffff; - FLASH_RES res = flash_file((uint8_t*)"/sd2snes/firmware.img"); - if(res == ERR_FLASHPREP || res == ERR_FLASHERASE || res == ERR_FLASH) { - rdyled(0); - writeled(1); - } - if(res == ERR_FILEHD || res == ERR_FILECHK) { - rdyled(0); - readled(1); - } - DBG_BL printf("flash result = %d\n", res); - if(res != ERR_OK) { - if((res = check_flash()) != ERR_OK) { - DBG_BL printf("check_flash() failed with error %d, not booting.\n", res); - while(1) { - toggle_rdy_led(); - delay_ms(500); - } + for ( i = 0; i < 20; i++ ) + { + uart_putc( '-' ); } - } - NVIC_DisableIRQ(RIT_IRQn); - NVIC_DisableIRQ(UART_IRQ); - SCB->VTOR=FW_START+0x00000100; - chain = (void*)(*((uint32_t*)(FW_START+0x00000104))); - uart_putc("0123456789abcdef"[((uint32_t)chain>>28)&15]); - uart_putc("0123456789abcdef"[((uint32_t)chain>>24)&15]); - uart_putc("0123456789abcdef"[((uint32_t)chain>>20)&15]); - uart_putc("0123456789abcdef"[((uint32_t)chain>>16)&15]); - uart_putc("0123456789abcdef"[((uint32_t)chain>>12)&15]); - uart_putc("0123456789abcdef"[((uint32_t)chain>>8)&15]); - uart_putc("0123456789abcdef"[((uint32_t)chain>>4)&15]); - uart_putc("0123456789abcdef"[((uint32_t)chain)&15]); - uart_putc('\n'); - chain(); - while(1); + uart_putc( '\n' ); + + DBG_BL printf( "chksum=%08lx\n", *( uint32_t * )28 ); + /*DBG_BL*/ printf( "\n\nsd2snes mk.2 bootloader\nver.: " VER "\ncpu clock: %ld Hz\n", CONFIG_CPU_FREQUENCY ); + DBG_BL printf( "PCONP=%lx\n", LPC_SC->PCONP ); + /* setup timer (fpga clk) */ + LPC_TIM3->CTCR = 0; + LPC_TIM3->EMR = EMC0TOGGLE; + LPC_TIM3->MCR = MR0R; + LPC_TIM3->MR0 = 1; + LPC_TIM3->TCR = 1; + NVIC->ICER[0] = 0xffffffff; + NVIC->ICER[1] = 0xffffffff; + FLASH_RES res = flash_file( ( uint8_t * )"/sd2snes/firmware.img" ); + + if ( res == ERR_FLASHPREP || res == ERR_FLASHERASE || res == ERR_FLASH ) + { + rdyled( 0 ); + writeled( 1 ); + } + + if ( res == ERR_FILEHD || res == ERR_FILECHK ) + { + rdyled( 0 ); + readled( 1 ); + } + + DBG_BL printf( "flash result = %d\n", res ); + + if ( res != ERR_OK ) + { + if ( ( res = check_flash() ) != ERR_OK ) + { + DBG_BL printf( "check_flash() failed with error %d, not booting.\n", res ); + + while ( 1 ) + { + toggle_rdy_led(); + delay_ms( 500 ); + } + } + } + + NVIC_DisableIRQ( RIT_IRQn ); + NVIC_DisableIRQ( UART_IRQ ); + + SCB->VTOR = FW_START + 0x00000100; + chain = ( void * )( *( ( uint32_t * )( FW_START + 0x00000104 ) ) ); + uart_putc( "0123456789abcdef"[( ( uint32_t )chain >> 28 ) & 15] ); + uart_putc( "0123456789abcdef"[( ( uint32_t )chain >> 24 ) & 15] ); + uart_putc( "0123456789abcdef"[( ( uint32_t )chain >> 20 ) & 15] ); + uart_putc( "0123456789abcdef"[( ( uint32_t )chain >> 16 ) & 15] ); + uart_putc( "0123456789abcdef"[( ( uint32_t )chain >> 12 ) & 15] ); + uart_putc( "0123456789abcdef"[( ( uint32_t )chain >> 8 ) & 15] ); + uart_putc( "0123456789abcdef"[( ( uint32_t )chain >> 4 ) & 15] ); + uart_putc( "0123456789abcdef"[( ( uint32_t )chain ) & 15] ); + uart_putc( '\n' ); + chain(); + + while ( 1 ); } diff --git a/src/bootldr/power.c b/src/bootldr/power.c index 848159c..0d46c42 100644 --- a/src/bootldr/power.c +++ b/src/bootldr/power.c @@ -15,12 +15,13 @@ * USB [enabled via usb_init] * PWM1 */ -void power_init() { - LPC_SC->PCONP = BV(PCSSP0) - | BV(PCTIM3) - | BV(PCRTC) - | BV(PCGPIO) - | BV(PCPWM1) -// | BV(PCUSB) - ; +void power_init() +{ + LPC_SC->PCONP = BV( PCSSP0 ) + | BV( PCTIM3 ) + | BV( PCRTC ) + | BV( PCGPIO ) + | BV( PCPWM1 ) + // | BV(PCUSB) + ; } diff --git a/src/bootldr/power.h b/src/bootldr/power.h index 65d3cac..e283c57 100644 --- a/src/bootldr/power.h +++ b/src/bootldr/power.h @@ -5,7 +5,7 @@ #include "bits.h" -#define PCUART0 (3) +#define PCUART0 (3) #define PCUART1 (4) #define PCUART2 (24) #define PCUART3 (25) @@ -38,6 +38,6 @@ #define PCQEI (18) #define PCGPIO (15) -void power_init(void); +void power_init( void ); #endif diff --git a/src/bootldr/printf.c b/src/bootldr/printf.c index a8988c9..6cefeef 100644 --- a/src/bootldr/printf.c +++ b/src/bootldr/printf.c @@ -62,239 +62,313 @@ static char *outptr; static int maxlen; /* printf */ -static void outchar(char x) { - if (maxlen) { - maxlen--; - outfunc(x); - outlength++; - } +static void outchar( char x ) +{ + if ( maxlen ) + { + maxlen--; + outfunc( x ); + outlength++; + } } /* sprintf */ -static void outstr(char x) { - if (maxlen) { - maxlen--; - *outptr++ = x; - outlength++; - } +static void outstr( char x ) +{ + if ( maxlen ) + { + maxlen--; + *outptr++ = x; + outlength++; + } } -static int internal_nprintf(void (*output_function)(char c), const char *fmt, va_list ap) { - unsigned int width; - unsigned int flags; - unsigned int base = 0; - char *ptr = NULL; +static int internal_nprintf( void ( *output_function )( char c ), const char *fmt, va_list ap ) +{ + unsigned int width; + unsigned int flags; + unsigned int base = 0; + char *ptr = NULL; - outlength = 0; + outlength = 0; - while (*fmt) { - while (1) { - if (*fmt == 0) - goto end; + while ( *fmt ) + { + while ( 1 ) + { + if ( *fmt == 0 ) + { + goto end; + } - if (*fmt == '%') { - fmt++; - if (*fmt != '%') - break; - } + if ( *fmt == '%' ) + { + fmt++; - output_function(*fmt++); - } + if ( *fmt != '%' ) + { + break; + } + } - flags = 0; - width = 0; - - /* read all flags */ - do { - if (flags < FLAG_WIDTH) { - switch (*fmt) { - case '0': - flags |= FLAG_ZEROPAD; - continue; - - case '-': - flags |= FLAG_LEFTADJ; - continue; - - case ' ': - flags |= FLAG_BLANK; - continue; - - case '+': - flags |= FLAG_FORCESIGN; - continue; - } - } - - if (flags < FLAG_LONG) { - if (*fmt >= '0' && *fmt <= '9') { - unsigned char tmp = *fmt - '0'; - width = 10*width + tmp; - flags |= FLAG_WIDTH; - continue; + output_function( *fmt++ ); } - if (*fmt == 'h') - continue; + flags = 0; + width = 0; - if (*fmt == 'l') { - flags |= FLAG_LONG; - continue; + /* read all flags */ + do + { + if ( flags < FLAG_WIDTH ) + { + switch ( *fmt ) + { + case '0': + flags |= FLAG_ZEROPAD; + continue; + + case '-': + flags |= FLAG_LEFTADJ; + continue; + + case ' ': + flags |= FLAG_BLANK; + continue; + + case '+': + flags |= FLAG_FORCESIGN; + continue; + } + } + + if ( flags < FLAG_LONG ) + { + if ( *fmt >= '0' && *fmt <= '9' ) + { + unsigned char tmp = *fmt - '0'; + width = 10 * width + tmp; + flags |= FLAG_WIDTH; + continue; + } + + if ( *fmt == 'h' ) + { + continue; + } + + if ( *fmt == 'l' ) + { + flags |= FLAG_LONG; + continue; + } + } + + break; } - } + while ( *fmt++ ); - break; - } while (*fmt++); + /* Strings */ + if ( *fmt == 'c' || *fmt == 's' ) + { + switch ( *fmt ) + { + case 'c': + buffer[0] = va_arg( ap, int ); + ptr = buffer; + break; - /* Strings */ - if (*fmt == 'c' || *fmt == 's') { - switch (*fmt) { - case 'c': - buffer[0] = va_arg(ap, int); - ptr = buffer; - break; + case 's': + ptr = va_arg( ap, char * ); + break; + } - case 's': - ptr = va_arg(ap, char *); - break; - } + goto output; + } - goto output; - } + /* Numbers */ + switch ( *fmt ) + { + case 'u': + flags |= FLAG_UNSIGNED; - /* Numbers */ - switch (*fmt) { - case 'u': - flags |= FLAG_UNSIGNED; - case 'd': - base = 10; - break; + case 'd': + base = 10; + break; - case 'o': - base = 8; - flags |= FLAG_UNSIGNED; - break; + case 'o': + base = 8; + flags |= FLAG_UNSIGNED; + break; - case 'p': // pointer - output_function('0'); - output_function('x'); - width -= 2; - case 'x': - case 'X': - base = 16; - flags |= FLAG_UNSIGNED; - break; - } + case 'p': // pointer + output_function( '0' ); + output_function( 'x' ); + width -= 2; - unsigned int num; + case 'x': + case 'X': + base = 16; + flags |= FLAG_UNSIGNED; + break; + } - if (!(flags & FLAG_UNSIGNED)) { - int tmp = va_arg(ap, int); - if (tmp < 0) { - num = -tmp; - flags |= FLAG_NEGATIVE; - } else - num = tmp; - } else { - num = va_arg(ap, unsigned int); - } + unsigned int num; - /* Convert number into buffer */ - ptr = buffer + sizeof(buffer); - *--ptr = 0; - do { - *--ptr = hexdigits[num % base]; - num /= base; - } while (num != 0); + if ( !( flags & FLAG_UNSIGNED ) ) + { + int tmp = va_arg( ap, int ); - /* Sign */ - if (flags & FLAG_NEGATIVE) { - output_function('-'); - width--; - } else if (flags & FLAG_FORCESIGN) { - output_function('+'); - width--; - } else if (flags & FLAG_BLANK) { - output_function(' '); - width--; - } - - output: - /* left padding */ - if ((flags & FLAG_WIDTH) && !(flags & FLAG_LEFTADJ)) { - while (strlen(ptr) < width) { - if (flags & FLAG_ZEROPAD) - output_function('0'); + if ( tmp < 0 ) + { + num = -tmp; + flags |= FLAG_NEGATIVE; + } + else + { + num = tmp; + } + } else - output_function(' '); - width--; - } + { + num = va_arg( ap, unsigned int ); + } + + /* Convert number into buffer */ + ptr = buffer + sizeof( buffer ); + *--ptr = 0; + + do + { + *--ptr = hexdigits[num % base]; + num /= base; + } + while ( num != 0 ); + + /* Sign */ + if ( flags & FLAG_NEGATIVE ) + { + output_function( '-' ); + width--; + } + else if ( flags & FLAG_FORCESIGN ) + { + output_function( '+' ); + width--; + } + else if ( flags & FLAG_BLANK ) + { + output_function( ' ' ); + width--; + } + +output: + + /* left padding */ + if ( ( flags & FLAG_WIDTH ) && !( flags & FLAG_LEFTADJ ) ) + { + while ( strlen( ptr ) < width ) + { + if ( flags & FLAG_ZEROPAD ) + { + output_function( '0' ); + } + else + { + output_function( ' ' ); + } + + width--; + } + } + + /* data */ + while ( *ptr ) + { + output_function( *ptr++ ); + + if ( width ) + { + width--; + } + } + + /* right padding */ + if ( flags & FLAG_WIDTH ) + { + while ( width ) + { + output_function( ' ' ); + width--; + } + } + + fmt++; } - /* data */ - while (*ptr) { - output_function(*ptr++); - if (width) - width--; - } - - /* right padding */ - if (flags & FLAG_WIDTH) { - while (width) { - output_function(' '); - width--; - } - } - - fmt++; - } - - end: - return outlength; +end: + return outlength; } -int printf(const char *format, ...) { - va_list ap; - int res; +int printf( const char *format, ... ) +{ + va_list ap; + int res; - maxlen = -1; - va_start(ap, format); - res = internal_nprintf(outchar, format, ap); - va_end(ap); - return res; + maxlen = -1; + va_start( ap, format ); + res = internal_nprintf( outchar, format, ap ); + va_end( ap ); + return res; } -int snprintf(char *str, size_t size, const char *format, ...) { - va_list ap; - int res; +int snprintf( char *str, size_t size, const char *format, ... ) +{ + va_list ap; + int res; - maxlen = size; - outptr = str; - va_start(ap, format); - res = internal_nprintf(outstr, format, ap); - va_end(ap); - if (res < size) - str[res] = 0; - return res; + maxlen = size; + outptr = str; + va_start( ap, format ); + res = internal_nprintf( outstr, format, ap ); + va_end( ap ); + + if ( res < size ) + { + str[res] = 0; + } + + return res; } /* Required for gcc compatibility */ -int puts(const char *str) { - uart_puts(str); - uart_putc('\n'); - return 0; +int puts( const char *str ) +{ + uart_puts( str ); + uart_putc( '\n' ); + return 0; } #undef putchar -int putchar(int c) { - uart_putc(c); - return 0; +int putchar( int c ) +{ + uart_putc( c ); + return 0; } #else -int printf(const char *format, ...) { return 0; } -int snprintf(char *str, size_t size, const char *format, ...) { return 0; } -int puts(const char *str) { return 0; } +int printf( const char *format, ... ) +{ + return 0; +} +//int snprintf(char *str, size_t size, const char *format, ...) { return 0; } +int puts( const char *str ) +{ + return 0; +} #undef putchar -int putchar(int c) { return 0; } +int putchar( int c ) +{ + return 0; +} #endif diff --git a/src/bootldr/sdnative.c b/src/bootldr/sdnative.c index 142b1f9..044c4b7 100644 --- a/src/bootldr/sdnative.c +++ b/src/bootldr/sdnative.c @@ -26,6 +26,7 @@ #define SEND_STATUS 13 #define SET_BLOCKLEN 16 #define READ_SINGLE_BLOCK 17 + #define READ_MULTIPLE_BLOCK 18 #define WRITE_BLOCK 24 #define WRITE_MULTIPLE_BLOCK 25 @@ -104,10 +105,10 @@ - CMD55: 0x77 0x00 0x00 0x00 0x00 0x65 */ -uint8_t cmd[6]={0,0,0,0,0,0}; +uint8_t cmd[6] = {0, 0, 0, 0, 0, 0}; uint8_t rsp[17]; uint8_t csd[17]; -uint8_t ccs=0; +uint8_t ccs = 0; uint32_t rca; enum trans_state { TRANS_NONE = 0, TRANS_READ, TRANS_WRITE }; @@ -129,114 +130,148 @@ volatile int sd_changed; * is assumed to be MSB first, passing 0 for start will read starting * from the highest-value bit of the first byte of the buffer. */ -static uint32_t getbits(void *buffer, uint16_t start, int8_t bits) { - uint8_t *buf = buffer; - uint32_t result = 0; +static uint32_t getbits( void *buffer, uint16_t start, int8_t bits ) +{ + uint8_t *buf = buffer; + uint32_t result = 0; - if ((start % 8) != 0) { - /* Unaligned start */ - result += buf[start / 8] & (0xff >> (start % 8)); - bits -= 8 - (start % 8); - start += 8 - (start % 8); - } - while (bits >= 8) { - result = (result << 8) + buf[start / 8]; - start += 8; - bits -= 8; - } - if (bits > 0) { - result = result << bits; - result = result + (buf[start / 8] >> (8-bits)); - } else if (bits < 0) { - /* Fraction of a single byte */ - result = result >> -bits; - } - return result; -} - -static inline void wiggle_slow_pos(uint16_t times) { - while(times--) { - delay_us(2); - BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1; - delay_us(2); - BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1; - } -} - -static inline void wiggle_slow_neg(uint16_t times) { - while(times--) { - delay_us(2); - BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1; - delay_us(2); - BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1; - } -} - -static inline void wiggle_fast_pos(uint16_t times) { - while(times--) { - BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1; - BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1; - } -} - -static inline void wiggle_fast_neg(uint16_t times) { - while(times--) { - BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1; - BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1; - } -} - -static inline void wiggle_fast_neg1(void) { - BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1; - BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1; -} - -static inline void wiggle_fast_pos1(void) { - BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1; - BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1; -} - -int get_and_check_datacrc(uint8_t *buf) { - uint16_t crc0=0, crc1=0, crc2=0, crc3=0; - uint16_t sdcrc0=0, sdcrc1=0, sdcrc2=0, sdcrc3=0; - uint8_t d0=0, d1=0, d2=0, d3=0; - uint8_t datdata; - uint16_t datcnt; - /* get crcs from card */ - for (datcnt=0; datcnt < 16; datcnt++) { - datdata = SD_DAT; - wiggle_fast_neg1(); - sdcrc0 = ((sdcrc0 << 1) & 0xfffe) | ((datdata >> 3) & 0x0001); - sdcrc1 = ((sdcrc1 << 1) & 0xfffe) | ((datdata >> 2) & 0x0001); - sdcrc2 = ((sdcrc2 << 1) & 0xfffe) | ((datdata >> 1) & 0x0001); - sdcrc3 = ((sdcrc3 << 1) & 0xfffe) | ((datdata >> 0) & 0x0001); - } - wiggle_fast_neg1(); - /* calc crcs from data */ - for (datcnt=0; datcnt < 512; datcnt++) { - d0 = ((d0 << 2) & 0xfc) | ((buf[datcnt] >> 6) & 0x02) | ((buf[datcnt] >> 3) & 0x01) ; - d1 = ((d1 << 2) & 0xfc) | ((buf[datcnt] >> 5) & 0x02) | ((buf[datcnt] >> 2) & 0x01) ; - d2 = ((d2 << 2) & 0xfc) | ((buf[datcnt] >> 4) & 0x02) | ((buf[datcnt] >> 1) & 0x01) ; - d3 = ((d3 << 2) & 0xfc) | ((buf[datcnt] >> 3) & 0x02) | ((buf[datcnt] >> 0) & 0x01) ; - if((datcnt % 4) == 3) { - crc0 = crc_xmodem_update(crc0, d0); - crc1 = crc_xmodem_update(crc1, d1); - crc2 = crc_xmodem_update(crc2, d2); - crc3 = crc_xmodem_update(crc3, d3); + if ( ( start % 8 ) != 0 ) + { + /* Unaligned start */ + result += buf[start / 8] & ( 0xff >> ( start % 8 ) ); + bits -= 8 - ( start % 8 ); + start += 8 - ( start % 8 ); } - } - if((crc0 != sdcrc0) || (crc1 != sdcrc1) || (crc2 != sdcrc2) || (crc3 != sdcrc3)) { - DBG_SD printf("CRC mismatch\nSDCRC CRC\n %04x %04x\n %04x %04x\n %04x %04x\n %04x %04x\n", sdcrc0, crc0, sdcrc1, crc1, sdcrc2, crc2, sdcrc3, crc3); - return 1; - } - return 0; + + while ( bits >= 8 ) + { + result = ( result << 8 ) + buf[start / 8]; + start += 8; + bits -= 8; + } + + if ( bits > 0 ) + { + result = result << bits; + result = result + ( buf[start / 8] >> ( 8 - bits ) ); + } + else if ( bits < 0 ) + { + /* Fraction of a single byte */ + result = result >> -bits; + } + + return result; } -static inline void wait_busy(void) { - while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) { +static inline void wiggle_slow_pos( uint16_t times ) +{ + while ( times-- ) + { + delay_us( 2 ); + BITBANG( SD_CLKREG->FIOSET, SD_CLKPIN ) = 1; + delay_us( 2 ); + BITBANG( SD_CLKREG->FIOCLR, SD_CLKPIN ) = 1; + } +} + +static inline void wiggle_slow_neg( uint16_t times ) +{ + while ( times-- ) + { + delay_us( 2 ); + BITBANG( SD_CLKREG->FIOCLR, SD_CLKPIN ) = 1; + delay_us( 2 ); + BITBANG( SD_CLKREG->FIOSET, SD_CLKPIN ) = 1; + } +} + +static inline void wiggle_fast_pos( uint16_t times ) +{ + while ( times-- ) + { + BITBANG( SD_CLKREG->FIOSET, SD_CLKPIN ) = 1; + BITBANG( SD_CLKREG->FIOCLR, SD_CLKPIN ) = 1; + } +} + +static inline void wiggle_fast_neg( uint16_t times ) +{ + while ( times-- ) + { + BITBANG( SD_CLKREG->FIOCLR, SD_CLKPIN ) = 1; + BITBANG( SD_CLKREG->FIOSET, SD_CLKPIN ) = 1; + } +} + +static inline void wiggle_fast_neg1( void ) +{ + BITBANG( SD_CLKREG->FIOCLR, SD_CLKPIN ) = 1; + BITBANG( SD_CLKREG->FIOSET, SD_CLKPIN ) = 1; +} + +static inline void wiggle_fast_pos1( void ) +{ + BITBANG( SD_CLKREG->FIOSET, SD_CLKPIN ) = 1; + BITBANG( SD_CLKREG->FIOCLR, SD_CLKPIN ) = 1; +} + +int get_and_check_datacrc( uint8_t *buf ) +{ + uint16_t crc0 = 0, crc1 = 0, crc2 = 0, crc3 = 0; + uint16_t sdcrc0 = 0, sdcrc1 = 0, sdcrc2 = 0, sdcrc3 = 0; + uint8_t d0 = 0, d1 = 0, d2 = 0, d3 = 0; + uint8_t datdata; + uint16_t datcnt; + + /* get crcs from card */ + for ( datcnt = 0; datcnt < 16; datcnt++ ) + { + datdata = SD_DAT; + wiggle_fast_neg1(); + sdcrc0 = ( ( sdcrc0 << 1 ) & 0xfffe ) | ( ( datdata >> 3 ) & 0x0001 ); + sdcrc1 = ( ( sdcrc1 << 1 ) & 0xfffe ) | ( ( datdata >> 2 ) & 0x0001 ); + sdcrc2 = ( ( sdcrc2 << 1 ) & 0xfffe ) | ( ( datdata >> 1 ) & 0x0001 ); + sdcrc3 = ( ( sdcrc3 << 1 ) & 0xfffe ) | ( ( datdata >> 0 ) & 0x0001 ); + } + wiggle_fast_neg1(); - } - wiggle_fast_neg(4); + + /* calc crcs from data */ + for ( datcnt = 0; datcnt < 512; datcnt++ ) + { + d0 = ( ( d0 << 2 ) & 0xfc ) | ( ( buf[datcnt] >> 6 ) & 0x02 ) | ( ( buf[datcnt] >> 3 ) & 0x01 ) ; + d1 = ( ( d1 << 2 ) & 0xfc ) | ( ( buf[datcnt] >> 5 ) & 0x02 ) | ( ( buf[datcnt] >> 2 ) & 0x01 ) ; + d2 = ( ( d2 << 2 ) & 0xfc ) | ( ( buf[datcnt] >> 4 ) & 0x02 ) | ( ( buf[datcnt] >> 1 ) & 0x01 ) ; + d3 = ( ( d3 << 2 ) & 0xfc ) | ( ( buf[datcnt] >> 3 ) & 0x02 ) | ( ( buf[datcnt] >> 0 ) & 0x01 ) ; + + if ( ( datcnt % 4 ) == 3 ) + { + crc0 = crc_xmodem_update( crc0, d0 ); + crc1 = crc_xmodem_update( crc1, d1 ); + crc2 = crc_xmodem_update( crc2, d2 ); + crc3 = crc_xmodem_update( crc3, d3 ); + } + } + + if ( ( crc0 != sdcrc0 ) || ( crc1 != sdcrc1 ) || ( crc2 != sdcrc2 ) || ( crc3 != sdcrc3 ) ) + { + DBG_SD printf( "CRC mismatch\nSDCRC CRC\n %04x %04x\n %04x %04x\n %04x %04x\n %04x %04x\n", sdcrc0, crc0, + sdcrc1, crc1, sdcrc2, crc2, sdcrc3, crc3 ); + return 1; + } + + return 0; +} + +static inline void wait_busy( void ) +{ + while ( !( BITBANG( SD_DAT0REG->FIOPIN, SD_DAT0PIN ) ) ) + { + wiggle_fast_neg1(); + } + + wiggle_fast_neg( 4 ); } /* @@ -244,69 +279,97 @@ static inline void wait_busy(void) { send SD command and put response in rsp. returns length of response or 0 if there was no response */ -int send_command_slow(uint8_t* cmd, uint8_t* rsp){ - uint8_t shift, i=6; - int rsplen; - uint8_t cmdno = *cmd & 0x3f; - wiggle_slow_pos(5); - switch(*cmd & 0x3f) { +int send_command_slow( uint8_t *cmd, uint8_t *rsp ) +{ + uint8_t shift, i = 6; + int rsplen; + uint8_t cmdno = *cmd & 0x3f; + wiggle_slow_pos( 5 ); + + switch ( *cmd & 0x3f ) + { case 0: - rsplen = 0; - break; + rsplen = 0; + break; + case 2: case 9: case 10: - rsplen = 17; - break; + rsplen = 17; + break; + default: - rsplen = 6; - } - /* send command */ - BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1; - - while(i--) { - shift = 8; - do { - shift--; - uint8_t data = *cmd; - *cmd<<=1; - if(data&0x80) { - BITBAND(SD_CMDREG->FIOSET, SD_CMDPIN) = 1; - } else { - BITBAND(SD_CMDREG->FIOCLR, SD_CMDPIN) = 1; - } - wiggle_slow_pos(1); - } while (shift); - cmd++; - } - - wiggle_slow_pos(1); - BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 0; - - if(rsplen) { - uint16_t timeout=1000; - while((BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) && --timeout) { - wiggle_slow_neg(1); - } - if(!timeout) { - DBG_SD printf("CMD%d timed out\n", cmdno); - return 0; /* no response within timeout */ + rsplen = 6; } - i=rsplen; - while(i--) { - shift = 8; - uint8_t data=0; - do { - shift--; - data |= (BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) << shift; - wiggle_slow_neg(1); - } while (shift); - *rsp=data; - rsp++; + /* send command */ + BITBANG( SD_CMDREG->FIODIR, SD_CMDPIN ) = 1; + + while ( i-- ) + { + shift = 8; + + do + { + shift--; + uint8_t data = *cmd; + *cmd <<= 1; + + if ( data & 0x80 ) + { + BITBANG( SD_CMDREG->FIOSET, SD_CMDPIN ) = 1; + } + else + { + BITBANG( SD_CMDREG->FIOCLR, SD_CMDPIN ) = 1; + } + + wiggle_slow_pos( 1 ); + } + while ( shift ); + + cmd++; } - } - return rsplen; + + wiggle_slow_pos( 1 ); + BITBANG( SD_CMDREG->FIODIR, SD_CMDPIN ) = 0; + + if ( rsplen ) + { + uint16_t timeout = 1000; + + while ( ( BITBANG( SD_CMDREG->FIOPIN, SD_CMDPIN ) ) && --timeout ) + { + wiggle_slow_neg( 1 ); + } + + if ( !timeout ) + { + DBG_SD printf( "CMD%d timed out\n", cmdno ); + return 0; /* no response within timeout */ + } + + i = rsplen; + + while ( i-- ) + { + shift = 8; + uint8_t data = 0; + + do + { + shift--; + data |= ( BITBANG( SD_CMDREG->FIOPIN, SD_CMDPIN ) ) << shift; + wiggle_slow_neg( 1 ); + } + while ( shift ); + + *rsp = data; + rsp++; + } + } + + return rsplen; } @@ -315,656 +378,935 @@ int send_command_slow(uint8_t* cmd, uint8_t* rsp){ send SD command and put response in rsp. returns length of response or 0 if there was no response */ -int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){ - uint8_t datshift=8, cmdshift, i=6; - uint8_t cmdno = *cmd & 0x3f; - int rsplen, dat=0, waitbusy=0, datcnt=512, j=0; - static int state=CMD_RSP; - wiggle_fast_pos(9); /* give the card >=8 cycles after last command */ - DBG_SD printf("send_command_fast: sending CMD%d; payload=%02x%02x%02x%02x%02x%02x...\n", cmdno, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5]); - switch(*cmd & 0x3f) { +int send_command_fast( uint8_t *cmd, uint8_t *rsp, uint8_t *buf ) +{ + uint8_t datshift = 8, cmdshift, i = 6; + uint8_t cmdno = *cmd & 0x3f; + int rsplen, dat = 0, waitbusy = 0, datcnt = 512, j = 0; + static int state = CMD_RSP; + wiggle_fast_pos( 9 ); /* give the card >=8 cycles after last command */ + DBG_SD printf( "send_command_fast: sending CMD%d; payload=%02x%02x%02x%02x%02x%02x...\n", cmdno, cmd[0], cmd[1], cmd[2], + cmd[3], cmd[4], cmd[5] ); + + switch ( *cmd & 0x3f ) + { case 0: - rsplen = 0; - break; + rsplen = 0; + break; + case 2: case 9: case 10: - rsplen = 17; - break; + rsplen = 17; + break; + case 12: - rsplen = 6; - waitbusy = 1; - break; + rsplen = 6; + waitbusy = 1; + break; + case 13: case 17: case 18: - dat = 1; + dat = 1; + default: - rsplen = 6; - } - if(dat && (buf==NULL)) { - DBG_SD printf("send_command_fast error: buf is null but data transfer expected.\n"); - return 0; - } - /* send command */ - BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1; - - while(i--) { - uint8_t data = *cmd; - cmdshift = 8; - do { - cmdshift--; - if(data&0x80) { - BITBAND(SD_CMDREG->FIOSET, SD_CMDPIN) = 1; - } else { - BITBAND(SD_CMDREG->FIOCLR, SD_CMDPIN) = 1; - } - data<<=1; - wiggle_fast_pos1(); - } while (cmdshift); - cmd++; - } - - wiggle_fast_pos1(); - BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 0; - - if(rsplen) { - uint32_t timeout=2000000; - /* wait for response */ - while((BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) && --timeout) { - wiggle_fast_neg1(); - } - if(!timeout) { - DBG_SD printf("CMD%d timed out\n", cmdno); - return 0; /* no response within timeout */ + rsplen = 6; } - i=rsplen; - uint8_t cmddata=0, datdata=0; - while(i--) { /* process response */ - cmdshift = 8; - do { - if(dat) { - if(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) { - DBG_SD printf("data start during response\n"); - j=datcnt; - state=CMD_RSPDAT; - break; - } + if ( dat && ( buf == NULL ) ) + { + DBG_SD printf( "send_command_fast error: buf is null but data transfer expected.\n" ); + return 0; + } + + /* send command */ + BITBANG( SD_CMDREG->FIODIR, SD_CMDPIN ) = 1; + + while ( i-- ) + { + uint8_t data = *cmd; + cmdshift = 8; + + do + { + cmdshift--; + + if ( data & 0x80 ) + { + BITBANG( SD_CMDREG->FIOSET, SD_CMDPIN ) = 1; + } + else + { + BITBANG( SD_CMDREG->FIOCLR, SD_CMDPIN ) = 1; + } + + data <<= 1; + wiggle_fast_pos1(); } - cmdshift--; - cmddata |= (BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) << cmdshift; - wiggle_fast_neg1(); - } while (cmdshift); - if(state==CMD_RSPDAT)break; - *rsp=cmddata; - cmddata=0; - rsp++; + while ( cmdshift ); + + cmd++; } - if(state==CMD_RSPDAT) { /* process response+data */ - int startbit=1; - DBG_SD printf("processing rsp+data cmdshift=%d i=%d j=%d\n", cmdshift, i, j); - datshift=8; - while(1) { - cmdshift--; - cmddata |= (BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) << cmdshift; - if(!cmdshift) { - cmdshift=8; - *rsp=cmddata; - cmddata=0; - rsp++; - i--; - if(!i) { - DBG_SD printf("response end\n"); - if(j) state=CMD_DAT; /* response over, remaining data */ - break; - } - } - if(!startbit) { - datshift-=4; - datdata |= SD_DAT << datshift; - if(!datshift) { - datshift=8; - *buf=datdata; - datdata=0; - buf++; - j--; - if(!j) break; - } - } - startbit=0; - wiggle_fast_neg1(); - } - } - - if(dat && state != CMD_DAT) { /* response ended before data */ - BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1; - state=CMD_DAT; - j=datcnt; - datshift=8; - DBG_SD printf("response over, waiting for data...\n"); - while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) { - wiggle_fast_neg1(); - } - wiggle_fast_neg1(); /* eat the start bit */ - } - - if(state==CMD_DAT) { /* transfer rest of data */ - DBG_SD printf("remaining data: %d\n", j); - if(datshift==8) { - while(1) { - datdata |= SD_DAT << 4; - wiggle_fast_neg1(); - - datdata |= SD_DAT; - wiggle_fast_neg1(); - - *buf=datdata; - datdata=0; - buf++; - j--; - if(!j) break; - } - } else { - - while(1) { - datshift-=4; - datdata |= SD_DAT << datshift; - if(!datshift) { - datshift=8; - *buf=datdata; - datdata=0; - buf++; - j--; - if(!j) break; - } - wiggle_fast_neg1(); - } - } - } - if(dat) { -#ifdef CONFIG_SD_DATACRC - if(get_and_check_datacrc(buf-512)) { - return CRC_ERROR; - } -#else - /* eat the crcs */ - wiggle_fast_neg(17); -#endif - } - - if(waitbusy) { - DBG_SD printf("waitbusy after send_cmd\n"); - wait_busy(); - } - state=CMD_RSP; - } - rsp-=rsplen; - DBG_SD printf("send_command_fast: CMD%d response: %02x%02x%02x%02x%02x%02x\n", cmdno, rsp[0], rsp[1], rsp[2], rsp[3], rsp[4], rsp[5]); - BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1; - return rsplen; -} - - -static inline void make_crc7(uint8_t* cmd) { - cmd[5]=crc7update(0, cmd[0]); - cmd[5]=crc7update(cmd[5], cmd[1]); - cmd[5]=crc7update(cmd[5], cmd[2]); - cmd[5]=crc7update(cmd[5], cmd[3]); - cmd[5]=crc7update(cmd[5], cmd[4]); - cmd[5]=(cmd[5] << 1) | 1; -} - -int cmd_slow(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) { - uint8_t cmdbuf[6]; - cmdbuf[0] = 0x40 | cmd; - cmdbuf[1] = param >> 24; - cmdbuf[2] = param >> 16; - cmdbuf[3] = param >> 8; - cmdbuf[4] = param; - if(!crc) { - make_crc7(cmdbuf); - } else { - cmdbuf[5] = crc; - } - return send_command_slow(cmdbuf, rsp); -} - -int acmd_slow(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) { - if(!(cmd_slow(APP_CMD, rca, 0, NULL, rsp))) { - return 0; - } - return cmd_slow(cmd, param, crc, dat, rsp); -} - -int cmd_fast(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) { - uint8_t cmdbuf[6]; - cmdbuf[0] = 0x40 | cmd; - cmdbuf[1] = param >> 24; - cmdbuf[2] = param >> 16; - cmdbuf[3] = param >> 8; - cmdbuf[4] = param; - if(!crc) { - make_crc7(cmdbuf); - } else { - cmdbuf[5] = crc; - } - return send_command_fast(cmdbuf, rsp, dat); -} - -int acmd_fast(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) { - if(!(cmd_fast(APP_CMD, rca, 0, NULL, rsp))) { - return 0; - } - return cmd_fast(cmd, param, crc, dat, rsp); -} - -int stream_datablock(uint8_t *buf) { -// uint8_t datshift=8; - int j=512; - uint8_t datdata=0; - uint32_t timeout=1000000; - - while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) { - wiggle_fast_neg1(); - } - wiggle_fast_neg1(); /* eat the start bit */ - while(1) { - datdata = SD_DAT << 4; - wiggle_fast_neg1(); - - datdata |= SD_DAT; - wiggle_fast_neg1(); - - *buf=datdata; - buf++; - j--; - if(!j) break; - } -#ifdef CONFIG_SD_DATACRC - return get_and_check_datacrc(buf-512); -#else - /* eat the crcs */ - wiggle_fast_neg(17); -#endif - return 0; -} - -void send_datablock(uint8_t *buf) { - uint16_t crc0=0, crc1=0, crc2=0, crc3=0, cnt=512; - uint8_t dat0=0, dat1=0, dat2=0, dat3=0, crcshift, datshift; - - wiggle_fast_pos1(); - BITBAND(SD_DAT0REG->FIODIR, SD_DAT0PIN) = 1; - BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 1; - BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 1; - BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 1; - - BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1; - BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1; - BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1; - BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1; - - wiggle_fast_pos1(); /* send start bit to card */ - crcshift=8; - while(cnt--) { - datshift=8; - do { - datshift-=4; - if(((*buf)>>datshift) & 0x8) { - BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1; - } else { - BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1; - } - if(((*buf)>>datshift) & 0x4) { - BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1; - } else { - BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1; - } - if(((*buf)>>datshift) & 0x2){ - BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1; - } else { - BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1; - } - if(((*buf)>>datshift) & 0x1){ - BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1; - } else { - BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1; - } - wiggle_fast_pos1(); - } while (datshift); - - crcshift-=2; - dat0 |= (((*buf)&0x01) | (((*buf)&0x10) >> 3)) << crcshift; - dat1 |= ((((*buf)&0x02) >> 1) | (((*buf)&0x20) >> 4)) << crcshift; - dat2 |= ((((*buf)&0x04) >> 2) | (((*buf)&0x40) >> 5)) << crcshift; - dat3 |= ((((*buf)&0x08) >> 3) | (((*buf)&0x80) >> 6)) << crcshift; - if(!crcshift) { - crc0 = crc_xmodem_update(crc0, dat0); - crc1 = crc_xmodem_update(crc1, dat1); - crc2 = crc_xmodem_update(crc2, dat2); - crc3 = crc_xmodem_update(crc3, dat3); - crcshift=8; - dat0=0; - dat1=0; - dat2=0; - dat3=0; - } - buf++; - } -// printf("crc0=%04x crc1=%04x crc2=%04x crc3=%04x ", crc0, crc1, crc2, crc3); - /* send crcs */ - datshift=16; - do { - datshift--; - if((crc0 >> datshift) & 1) { - BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1; - } else { - BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1; - } - if((crc1 >> datshift) & 1) { - BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1; - } else { - BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1; - } - if((crc2 >> datshift) & 1) { - BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1; - } else { - BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1; - } - if((crc3 >> datshift) & 1) { - BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1; - } else { - BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1; - } wiggle_fast_pos1(); - } while(datshift); - /* send end bit */ - BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1; - BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1; - BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1; - BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1; + BITBANG( SD_CMDREG->FIODIR, SD_CMDPIN ) = 0; - wiggle_fast_pos1(); + if ( rsplen ) + { + uint32_t timeout = 2000000; - BITBAND(SD_DAT0REG->FIODIR, SD_DAT0PIN) = 0; - BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 0; - BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 0; - BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 0; + /* wait for response */ + while ( ( BITBANG( SD_CMDREG->FIOPIN, SD_CMDPIN ) ) && --timeout ) + { + wiggle_fast_neg1(); + } - wiggle_fast_neg(3); - dat0=0; + if ( !timeout ) + { + DBG_SD printf( "CMD%d timed out\n", cmdno ); + return 0; /* no response within timeout */ + } - datshift=4; - do { - datshift--; - dat0 |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) << datshift); - wiggle_fast_neg1(); - } while (datshift); - DBG_SD printf("crc %02x\n", dat0); - if((dat0 & 7) != 2) { - DBG_SD printf("crc error! %02x\n", dat0); - while(1); - } - if(dat0 & 8) { - DBG_SD printf("missing start bit in CRC status response...\n"); - } - wiggle_fast_neg(2); - wait_busy(); + i = rsplen; + uint8_t cmddata = 0, datdata = 0; + + while ( i-- ) /* process response */ + { + cmdshift = 8; + + do + { + if ( dat ) + { + if ( !( BITBANG( SD_DAT0REG->FIOPIN, SD_DAT0PIN ) ) ) + { + DBG_SD printf( "data start during response\n" ); + j = datcnt; + state = CMD_RSPDAT; + break; + } + } + + cmdshift--; + cmddata |= ( BITBANG( SD_CMDREG->FIOPIN, SD_CMDPIN ) ) << cmdshift; + wiggle_fast_neg1(); + } + while ( cmdshift ); + + if ( state == CMD_RSPDAT ) + { + break; + } + + *rsp = cmddata; + cmddata = 0; + rsp++; + } + + if ( state == CMD_RSPDAT ) /* process response+data */ + { + int startbit = 1; + DBG_SD printf( "processing rsp+data cmdshift=%d i=%d j=%d\n", cmdshift, i, j ); + datshift = 8; + + while ( 1 ) + { + cmdshift--; + cmddata |= ( BITBANG( SD_CMDREG->FIOPIN, SD_CMDPIN ) ) << cmdshift; + + if ( !cmdshift ) + { + cmdshift = 8; + *rsp = cmddata; + cmddata = 0; + rsp++; + i--; + + if ( !i ) + { + DBG_SD printf( "response end\n" ); + + if ( j ) + { + state = CMD_DAT; /* response over, remaining data */ + } + + break; + } + } + + if ( !startbit ) + { + datshift -= 4; + datdata |= SD_DAT << datshift; + + if ( !datshift ) + { + datshift = 8; + *buf = datdata; + datdata = 0; + buf++; + j--; + + if ( !j ) + { + break; + } + } + } + + startbit = 0; + wiggle_fast_neg1(); + } + } + + if ( dat && state != CMD_DAT ) /* response ended before data */ + { + BITBANG( SD_CMDREG->FIODIR, SD_CMDPIN ) = 1; + state = CMD_DAT; + j = datcnt; + datshift = 8; + DBG_SD printf( "response over, waiting for data...\n" ); + + while ( ( BITBANG( SD_DAT0REG->FIOPIN, SD_DAT0PIN ) ) && --timeout ) + { + wiggle_fast_neg1(); + } + + wiggle_fast_neg1(); /* eat the start bit */ + } + + if ( state == CMD_DAT ) /* transfer rest of data */ + { + DBG_SD printf( "remaining data: %d\n", j ); + + if ( datshift == 8 ) + { + while ( 1 ) + { + datdata |= SD_DAT << 4; + wiggle_fast_neg1(); + + datdata |= SD_DAT; + wiggle_fast_neg1(); + + *buf = datdata; + datdata = 0; + buf++; + j--; + + if ( !j ) + { + break; + } + } + } + else + { + + while ( 1 ) + { + datshift -= 4; + datdata |= SD_DAT << datshift; + + if ( !datshift ) + { + datshift = 8; + *buf = datdata; + datdata = 0; + buf++; + j--; + + if ( !j ) + { + break; + } + } + + wiggle_fast_neg1(); + } + } + } + + if ( dat ) + { +#ifdef CONFIG_SD_DATACRC + + if ( get_and_check_datacrc( buf - 512 ) ) + { + return CRC_ERROR; + } + +#else + /* eat the crcs */ + wiggle_fast_neg( 17 ); +#endif + } + + if ( waitbusy ) + { + DBG_SD printf( "waitbusy after send_cmd\n" ); + wait_busy(); + } + + state = CMD_RSP; + } + + rsp -= rsplen; + DBG_SD printf( "send_command_fast: CMD%d response: %02x%02x%02x%02x%02x%02x\n", cmdno, rsp[0], rsp[1], rsp[2], rsp[3], + rsp[4], rsp[5] ); + BITBANG( SD_CMDREG->FIODIR, SD_CMDPIN ) = 1; + return rsplen; } -void read_block(uint32_t address, uint8_t *buf) { - if(during_blocktrans == TRANS_READ && (last_block == address-1)) { -//uart_putc('r'); -#ifdef CONFIG_SD_DATACRC - int cmd_res; - if((cmd_res = stream_datablock(buf)) == CRC_ERROR) { - while(cmd_res == CRC_ERROR) { - cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp); - cmd_res = cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp); - } - } -#else - stream_datablock(buf); -#endif - last_block=address; - } else { - if(during_blocktrans) { -// uart_putc('_'); -//printf("nonseq read (%lx -> %lx), restarting transmission\n", last_block, address); - /* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */ - cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp); - } - last_block=address; - if(!ccs) { - address <<= 9; - } -#ifdef CONFIG_SD_DATACRC - while(1) { - if(cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp) != CRC_ERROR) break; - cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp); - }; -#else - cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp); -#endif - during_blocktrans = TRANS_READ; - } + +static inline void make_crc7( uint8_t *cmd ) +{ + cmd[5] = crc7update( 0, cmd[0] ); + cmd[5] = crc7update( cmd[5], cmd[1] ); + cmd[5] = crc7update( cmd[5], cmd[2] ); + cmd[5] = crc7update( cmd[5], cmd[3] ); + cmd[5] = crc7update( cmd[5], cmd[4] ); + cmd[5] = ( cmd[5] << 1 ) | 1; } -void write_block(uint32_t address, uint8_t* buf) { - if(during_blocktrans == TRANS_WRITE && (last_block == address-1)) { - wait_busy(); - send_datablock(buf); - last_block=address; - } else { - if(during_blocktrans) { - /* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */ - cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp); +int cmd_slow( uint8_t cmd, uint32_t param, uint8_t crc, uint8_t *dat, uint8_t *rsp ) +{ + uint8_t cmdbuf[6]; + cmdbuf[0] = 0x40 | cmd; + cmdbuf[1] = param >> 24; + cmdbuf[2] = param >> 16; + cmdbuf[3] = param >> 8; + cmdbuf[4] = param; + + if ( !crc ) + { + make_crc7( cmdbuf ); } - wait_busy(); - last_block=address; - if(!ccs) { - address <<= 9; + else + { + cmdbuf[5] = crc; + } + + return send_command_slow( cmdbuf, rsp ); +} + +int acmd_slow( uint8_t cmd, uint32_t param, uint8_t crc, uint8_t *dat, uint8_t *rsp ) +{ + if ( !( cmd_slow( APP_CMD, rca, 0, NULL, rsp ) ) ) + { + return 0; + } + + return cmd_slow( cmd, param, crc, dat, rsp ); +} + +int cmd_fast( uint8_t cmd, uint32_t param, uint8_t crc, uint8_t *dat, uint8_t *rsp ) +{ + uint8_t cmdbuf[6]; + cmdbuf[0] = 0x40 | cmd; + cmdbuf[1] = param >> 24; + cmdbuf[2] = param >> 16; + cmdbuf[3] = param >> 8; + cmdbuf[4] = param; + + if ( !crc ) + { + make_crc7( cmdbuf ); + } + else + { + cmdbuf[5] = crc; + } + + return send_command_fast( cmdbuf, rsp, dat ); +} + +int acmd_fast( uint8_t cmd, uint32_t param, uint8_t crc, uint8_t *dat, uint8_t *rsp ) +{ + if ( !( cmd_fast( APP_CMD, rca, 0, NULL, rsp ) ) ) + { + return 0; + } + + return cmd_fast( cmd, param, crc, dat, rsp ); +} + +int stream_datablock( uint8_t *buf ) +{ + // uint8_t datshift=8; + int j = 512; + uint8_t datdata = 0; + uint32_t timeout = 1000000; + + while ( ( BITBANG( SD_DAT0REG->FIOPIN, SD_DAT0PIN ) ) && --timeout ) + { + wiggle_fast_neg1(); + } + + wiggle_fast_neg1(); /* eat the start bit */ + + while ( 1 ) + { + datdata = SD_DAT << 4; + wiggle_fast_neg1(); + + datdata |= SD_DAT; + wiggle_fast_neg1(); + + *buf = datdata; + buf++; + j--; + + if ( !j ) + { + break; + } + } + +#ifdef CONFIG_SD_DATACRC + return get_and_check_datacrc( buf - 512 ); +#else + /* eat the crcs */ + wiggle_fast_neg( 17 ); +#endif + return 0; +} + +void send_datablock( uint8_t *buf ) +{ + uint16_t crc0 = 0, crc1 = 0, crc2 = 0, crc3 = 0, cnt = 512; + uint8_t dat0 = 0, dat1 = 0, dat2 = 0, dat3 = 0, crcshift, datshift; + + wiggle_fast_pos1(); + BITBANG( SD_DAT0REG->FIODIR, SD_DAT0PIN ) = 1; + BITBANG( SD_DAT1REG->FIODIR, SD_DAT1PIN ) = 1; + BITBANG( SD_DAT2REG->FIODIR, SD_DAT2PIN ) = 1; + BITBANG( SD_DAT3REG->FIODIR, SD_DAT3PIN ) = 1; + + BITBANG( SD_DAT0REG->FIOCLR, SD_DAT0PIN ) = 1; + BITBANG( SD_DAT1REG->FIOCLR, SD_DAT1PIN ) = 1; + BITBANG( SD_DAT2REG->FIOCLR, SD_DAT2PIN ) = 1; + BITBANG( SD_DAT3REG->FIOCLR, SD_DAT3PIN ) = 1; + + wiggle_fast_pos1(); /* send start bit to card */ + crcshift = 8; + + while ( cnt-- ) + { + datshift = 8; + + do + { + datshift -= 4; + + if ( ( ( *buf ) >> datshift ) & 0x8 ) + { + BITBANG( SD_DAT3REG->FIOSET, SD_DAT3PIN ) = 1; + } + else + { + BITBANG( SD_DAT3REG->FIOCLR, SD_DAT3PIN ) = 1; + } + + if ( ( ( *buf ) >> datshift ) & 0x4 ) + { + BITBANG( SD_DAT2REG->FIOSET, SD_DAT2PIN ) = 1; + } + else + { + BITBANG( SD_DAT2REG->FIOCLR, SD_DAT2PIN ) = 1; + } + + if ( ( ( *buf ) >> datshift ) & 0x2 ) + { + BITBANG( SD_DAT1REG->FIOSET, SD_DAT1PIN ) = 1; + } + else + { + BITBANG( SD_DAT1REG->FIOCLR, SD_DAT1PIN ) = 1; + } + + if ( ( ( *buf ) >> datshift ) & 0x1 ) + { + BITBANG( SD_DAT0REG->FIOSET, SD_DAT0PIN ) = 1; + } + else + { + BITBANG( SD_DAT0REG->FIOCLR, SD_DAT0PIN ) = 1; + } + + wiggle_fast_pos1(); + } + while ( datshift ); + + crcshift -= 2; + dat0 |= ( ( ( *buf ) & 0x01 ) | ( ( ( *buf ) & 0x10 ) >> 3 ) ) << crcshift; + dat1 |= ( ( ( ( *buf ) & 0x02 ) >> 1 ) | ( ( ( *buf ) & 0x20 ) >> 4 ) ) << crcshift; + dat2 |= ( ( ( ( *buf ) & 0x04 ) >> 2 ) | ( ( ( *buf ) & 0x40 ) >> 5 ) ) << crcshift; + dat3 |= ( ( ( ( *buf ) & 0x08 ) >> 3 ) | ( ( ( *buf ) & 0x80 ) >> 6 ) ) << crcshift; + + if ( !crcshift ) + { + crc0 = crc_xmodem_update( crc0, dat0 ); + crc1 = crc_xmodem_update( crc1, dat1 ); + crc2 = crc_xmodem_update( crc2, dat2 ); + crc3 = crc_xmodem_update( crc3, dat3 ); + crcshift = 8; + dat0 = 0; + dat1 = 0; + dat2 = 0; + dat3 = 0; + } + + buf++; + } + + // printf("crc0=%04x crc1=%04x crc2=%04x crc3=%04x ", crc0, crc1, crc2, crc3); + /* send crcs */ + datshift = 16; + + do + { + datshift--; + + if ( ( crc0 >> datshift ) & 1 ) + { + BITBANG( SD_DAT0REG->FIOSET, SD_DAT0PIN ) = 1; + } + else + { + BITBANG( SD_DAT0REG->FIOCLR, SD_DAT0PIN ) = 1; + } + + if ( ( crc1 >> datshift ) & 1 ) + { + BITBANG( SD_DAT1REG->FIOSET, SD_DAT1PIN ) = 1; + } + else + { + BITBANG( SD_DAT1REG->FIOCLR, SD_DAT1PIN ) = 1; + } + + if ( ( crc2 >> datshift ) & 1 ) + { + BITBANG( SD_DAT2REG->FIOSET, SD_DAT2PIN ) = 1; + } + else + { + BITBANG( SD_DAT2REG->FIOCLR, SD_DAT2PIN ) = 1; + } + + if ( ( crc3 >> datshift ) & 1 ) + { + BITBANG( SD_DAT3REG->FIOSET, SD_DAT3PIN ) = 1; + } + else + { + BITBANG( SD_DAT3REG->FIOCLR, SD_DAT3PIN ) = 1; + } + + wiggle_fast_pos1(); + } + while ( datshift ); + + /* send end bit */ + BITBANG( SD_DAT0REG->FIOSET, SD_DAT0PIN ) = 1; + BITBANG( SD_DAT1REG->FIOSET, SD_DAT1PIN ) = 1; + BITBANG( SD_DAT2REG->FIOSET, SD_DAT2PIN ) = 1; + BITBANG( SD_DAT3REG->FIOSET, SD_DAT3PIN ) = 1; + + wiggle_fast_pos1(); + + BITBANG( SD_DAT0REG->FIODIR, SD_DAT0PIN ) = 0; + BITBANG( SD_DAT1REG->FIODIR, SD_DAT1PIN ) = 0; + BITBANG( SD_DAT2REG->FIODIR, SD_DAT2PIN ) = 0; + BITBANG( SD_DAT3REG->FIODIR, SD_DAT3PIN ) = 0; + + wiggle_fast_neg( 3 ); + dat0 = 0; + + datshift = 4; + + do + { + datshift--; + dat0 |= ( ( BITBANG( SD_DAT0REG->FIOPIN, SD_DAT0PIN ) ) << datshift ); + wiggle_fast_neg1(); + } + while ( datshift ); + + DBG_SD printf( "crc %02x\n", dat0 ); + + if ( ( dat0 & 7 ) != 2 ) + { + DBG_SD printf( "crc error! %02x\n", dat0 ); + + while ( 1 ); + } + + if ( dat0 & 8 ) + { + DBG_SD printf( "missing start bit in CRC status response...\n" ); + } + + wiggle_fast_neg( 2 ); + wait_busy(); +} + +void read_block( uint32_t address, uint8_t *buf ) +{ + if ( during_blocktrans == TRANS_READ && ( last_block == address - 1 ) ) + { + //uart_putc('r'); +#ifdef CONFIG_SD_DATACRC + int cmd_res; + + if ( ( cmd_res = stream_datablock( buf ) ) == CRC_ERROR ) + { + while ( cmd_res == CRC_ERROR ) + { + cmd_fast( STOP_TRANSMISSION, 0, 0x61, NULL, rsp ); + cmd_res = cmd_fast( READ_MULTIPLE_BLOCK, address, 0, buf, rsp ); + } + } + +#else + stream_datablock( buf ); +#endif + last_block = address; + } + else + { + if ( during_blocktrans ) + { + // uart_putc('_'); + //printf("nonseq read (%lx -> %lx), restarting transmission\n", last_block, address); + /* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */ + cmd_fast( STOP_TRANSMISSION, 0, 0x61, NULL, rsp ); + } + + last_block = address; + + if ( !ccs ) + { + address <<= 9; + } + +#ifdef CONFIG_SD_DATACRC + + while ( 1 ) + { + if ( cmd_fast( READ_MULTIPLE_BLOCK, address, 0, buf, rsp ) != CRC_ERROR ) + { + break; + } + + cmd_fast( STOP_TRANSMISSION, 0, 0x61, NULL, rsp ); + }; + +#else + cmd_fast( READ_MULTIPLE_BLOCK, address, 0, buf, rsp ); + +#endif + during_blocktrans = TRANS_READ; + } +} + +void write_block( uint32_t address, uint8_t *buf ) +{ + if ( during_blocktrans == TRANS_WRITE && ( last_block == address - 1 ) ) + { + wait_busy(); + send_datablock( buf ); + last_block = address; + } + else + { + if ( during_blocktrans ) + { + /* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */ + cmd_fast( STOP_TRANSMISSION, 0, 0x61, NULL, rsp ); + } + + wait_busy(); + last_block = address; + + if ( !ccs ) + { + address <<= 9; + } + + /* only send cmd & get response */ + cmd_fast( WRITE_MULTIPLE_BLOCK, address, 0, NULL, rsp ); + DBG_SD printf( "write_block: CMD25 response = %02x%02x%02x%02x%02x%02x\n", rsp[0], rsp[1], rsp[2], rsp[3], rsp[4], + rsp[5] ); + wiggle_fast_pos( 8 ); + send_datablock( buf ); + during_blocktrans = TRANS_WRITE; } - /* only send cmd & get response */ - cmd_fast(WRITE_MULTIPLE_BLOCK, address, 0, NULL, rsp); - DBG_SD printf("write_block: CMD25 response = %02x%02x%02x%02x%02x%02x\n", rsp[0], rsp[1], rsp[2], rsp[3], rsp[4], rsp[5]); - wiggle_fast_pos(8); - send_datablock(buf); - during_blocktrans = TRANS_WRITE; - } } // // Public functions // -DRESULT sdn_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count) { - uint8_t sec; - if(drv >= MAX_CARDS) { - return RES_PARERR; - } - readled(1); - for(sec=0; sec=MAX_CARDS) { - return STA_NOINIT|STA_NODISK; - } - - if(sdn_status(drv) & STA_NODISK) { - return STA_NOINIT|STA_NODISK; - } - /* if the card is sending data from before a reset we try to deselect it - prior to initialization */ - for(rsplen=0; rsplen<2042; rsplen++) { - if(!(BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN))) { - DBG_SD printf("card seems to be sending data, attempting deselect\n"); - cmd_slow(SELECT_CARD, 0, 0, NULL, rsp); + if ( drv >= MAX_CARDS ) + { + return RES_PARERR; } - wiggle_slow_neg(1); - } - DBG_SD printf("sd_init start\n"); - cmd_slow(GO_IDLE_STATE, 0, 0x95, NULL, rsp); - if((rsplen=cmd_slow(SEND_IF_COND, 0x000001aa, 0x87, NULL, rsp))) { - DBG_SD printf("CMD8 response:\n"); - DBG_SD uart_trace(rsp, 0, rsplen); - hcs=1; - } - while(1) { - if(!(acmd_slow(SD_SEND_OP_COND, (hcs << 30) | 0xfc0000, 0, NULL, rsp))) { - DBG_SD printf("ACMD41 no response!\n"); + readled( 1 ); + + for ( sec = 0; sec < count; sec++ ) + { + read_block( sector + sec, buffer ); + buffer += 512; } - if(rsp[1]&0x80) break; - } - ccs = (rsp[1]>>6) & 1; /* SDHC/XC */ - - cmd_slow(ALL_SEND_CID, 0, 0x4d, NULL, rsp); - if(cmd_slow(SEND_RELATIVE_ADDR, 0, 0x21, NULL, rsp)) { - rca=(rsp[1]<<24) | (rsp[2]<<16); - DBG_SD printf("RCA: %04lx\n", rca>>16); - } else { - DBG_SD printf("CMD3 no response!\n"); - rca=0; - } - - /* record CSD for getinfo */ - cmd_slow(SEND_CSD, rca, 0, NULL, rsp); - - /* select the card */ - if(cmd_slow(SELECT_CARD, rca, 0, NULL, rsp)) { - DBG_SD printf("card selected!\n"); - } else { - DBG_SD printf("CMD7 no response!\n"); - } - - /* get card status */ - cmd_slow(SEND_STATUS, rca, 0, NULL, rsp); - - /* set bus width */ - acmd_slow(SD_SET_BUS_WIDTH, 0x2, 0, NULL, rsp); - - /* set block length */ - cmd_slow(SET_BLOCKLEN, 0x200, 0, NULL, rsp); - - DBG_SD printf("SD init complete. SDHC/XC=%d\n", ccs); - disk_state = DISK_OK; - during_blocktrans = TRANS_NONE; - return sdn_status(drv); + readled( 0 ); + return RES_OK; } +DRESULT disk_read( BYTE drv, BYTE *buffer, DWORD sector, BYTE count ) __attribute__ ( ( weak, alias( "sdn_read" ) ) ); -DSTATUS disk_initialize(BYTE drv) __attribute__ ((weak, alias("sdn_initialize"))); +DRESULT sdn_initialize( BYTE drv ) +{ -void sdn_init(void) { - /* enable GPIO interrupt on SD detect pin, both edges */ -/* NVIC_EnableIRQ(EINT3_IRQn); - SD_DT_INT_SETUP(); */ - /* disconnect SSP1 */ - LPC_PINCON->PINSEL0 &= ~(BV(13) | BV(15) | BV(17) | BV(19)); - /* prepare GPIOs */ - BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 0; - BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 0; - BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 0; - BITBAND(SD_DAT0REG->FIODIR, SD_DAT0PIN) = 0; - BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 1; - BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1; - BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN) = 1; -} -void disk_init(void) __attribute__ ((weak, alias("sdn_init"))); + uint8_t rsp[17]; /* space for response */ + int rsplen; + uint8_t hcs = 0; + rca = 0; - -DSTATUS sdn_status(BYTE drv) { - if (SDCARD_DETECT) { - if (SDCARD_WP) { - return STA_PROTECT; - } else { - return RES_OK; + if ( drv >= MAX_CARDS ) + { + return STA_NOINIT | STA_NODISK; } - } else { - return STA_NOINIT|STA_NODISK; - } -} -DSTATUS disk_status(BYTE drv) __attribute__ ((weak, alias("sdn_status"))); -DRESULT sdn_getinfo(BYTE drv, BYTE page, void *buffer) { - uint32_t capacity; + if ( sdn_status( drv ) & STA_NODISK ) + { + return STA_NOINIT | STA_NODISK; + } - if (drv >= MAX_CARDS) { - return RES_NOTRDY; - } - if (sdn_status(drv) & STA_NODISK) { - return RES_NOTRDY; - } - if (page != 0) { - return RES_ERROR; - } - if (ccs) { - /* Special CSD for SDHC cards */ - capacity = (1 + getbits(csd,127-69+8,22)) * 1024; - } else { - /* Assume that MMC-CSD 1.0/1.1/1.2 and SD-CSD 1.1 are the same... */ - uint8_t exponent = 2 + getbits(csd, 127-49+8, 3); - capacity = 1 + getbits(csd, 127-73+8, 12); - exponent += getbits(csd, 127-83+8,4) - 9; - while (exponent--) capacity *= 2; - } + /* if the card is sending data from before a reset we try to deselect it + prior to initialization */ + for ( rsplen = 0; rsplen < 2042; rsplen++ ) + { + if ( !( BITBANG( SD_DAT3REG->FIOPIN, SD_DAT3PIN ) ) ) + { + DBG_SD printf( "card seems to be sending data, attempting deselect\n" ); + cmd_slow( SELECT_CARD, 0, 0, NULL, rsp ); + } - diskinfo0_t *di = buffer; - di->validbytes = sizeof(diskinfo0_t); - di->disktype = DISK_TYPE_SD; - di->sectorsize = 2; - di->sectorcount = capacity; + wiggle_slow_neg( 1 ); + } - DBG_SD printf("card capacity: %lu sectors\n", capacity); - return RES_OK; -} -DRESULT disk_getinfo(BYTE drv, BYTE page, void *buffer) __attribute__ ((weak, alias("sdn_getinfo"))); + DBG_SD printf( "sd_init start\n" ); + cmd_slow( GO_IDLE_STATE, 0, 0x95, NULL, rsp ); -DRESULT sdn_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) { - uint8_t sec; - uint8_t *buf = (uint8_t*)buffer; - if(drv >= MAX_CARDS) { - return RES_NOTRDY; - } - if (sdn_status(drv) & STA_NODISK) { - return RES_NOTRDY; - } - writeled(1); - for(sec=0; sec> 6 ) & 1; /* SDHC/XC */ + + cmd_slow( ALL_SEND_CID, 0, 0x4d, NULL, rsp ); + + if ( cmd_slow( SEND_RELATIVE_ADDR, 0, 0x21, NULL, rsp ) ) + { + rca = ( rsp[1] << 24 ) | ( rsp[2] << 16 ); + DBG_SD printf( "RCA: %04lx\n", rca >> 16 ); + } + else + { + DBG_SD printf( "CMD3 no response!\n" ); + rca = 0; + } + + /* record CSD for getinfo */ + cmd_slow( SEND_CSD, rca, 0, NULL, rsp ); + + /* select the card */ + if ( cmd_slow( SELECT_CARD, rca, 0, NULL, rsp ) ) + { + DBG_SD printf( "card selected!\n" ); + } + else + { + DBG_SD printf( "CMD7 no response!\n" ); + } + + /* get card status */ + cmd_slow( SEND_STATUS, rca, 0, NULL, rsp ); + + /* set bus width */ + acmd_slow( SD_SET_BUS_WIDTH, 0x2, 0, NULL, rsp ); + + /* set block length */ + cmd_slow( SET_BLOCKLEN, 0x200, 0, NULL, rsp ); + + DBG_SD printf( "SD init complete. SDHC/XC=%d\n", ccs ); + disk_state = DISK_OK; + during_blocktrans = TRANS_NONE; + return sdn_status( drv ); } -DRESULT disk_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) __attribute__ ((weak, alias("sdn_write"))); +DSTATUS disk_initialize( BYTE drv ) __attribute__ ( ( weak, alias( "sdn_initialize" ) ) ); + +void sdn_init( void ) +{ + /* enable GPIO interrupt on SD detect pin, both edges */ + /* NVIC_EnableIRQ(EINT3_IRQn); + SD_DT_INT_SETUP(); */ + /* disconnect SSP1 */ + LPC_PINCON->PINSEL0 &= ~( BV( 13 ) | BV( 15 ) | BV( 17 ) | BV( 19 ) ); + /* prepare GPIOs */ + BITBANG( SD_DAT3REG->FIODIR, SD_DAT3PIN ) = 0; + BITBANG( SD_DAT2REG->FIODIR, SD_DAT2PIN ) = 0; + BITBANG( SD_DAT1REG->FIODIR, SD_DAT1PIN ) = 0; + BITBANG( SD_DAT0REG->FIODIR, SD_DAT0PIN ) = 0; + BITBANG( SD_CLKREG->FIODIR, SD_CLKPIN ) = 1; + BITBANG( SD_CMDREG->FIODIR, SD_CMDPIN ) = 1; + BITBANG( SD_CMDREG->FIOPIN, SD_CMDPIN ) = 1; +} +void disk_init( void ) __attribute__ ( ( weak, alias( "sdn_init" ) ) ); + + +DSTATUS sdn_status( BYTE drv ) +{ + if ( SDCARD_DETECT ) + { + if ( SDCARD_WP ) + { + return STA_PROTECT; + } + else + { + return RES_OK; + } + } + else + { + return STA_NOINIT | STA_NODISK; + } +} +DSTATUS disk_status( BYTE drv ) __attribute__ ( ( weak, alias( "sdn_status" ) ) ); + +DRESULT sdn_getinfo( BYTE drv, BYTE page, void *buffer ) +{ + uint32_t capacity; + + if ( drv >= MAX_CARDS ) + { + return RES_NOTRDY; + } + + if ( sdn_status( drv ) & STA_NODISK ) + { + return RES_NOTRDY; + } + + if ( page != 0 ) + { + return RES_ERROR; + } + + if ( ccs ) + { + /* Special CSD for SDHC cards */ + capacity = ( 1 + getbits( csd, 127 - 69 + 8, 22 ) ) * 1024; + } + else + { + /* Assume that MMC-CSD 1.0/1.1/1.2 and SD-CSD 1.1 are the same... */ + uint8_t exponent = 2 + getbits( csd, 127 - 49 + 8, 3 ); + capacity = 1 + getbits( csd, 127 - 73 + 8, 12 ); + exponent += getbits( csd, 127 - 83 + 8, 4 ) - 9; + + while ( exponent-- ) + { + capacity *= 2; + } + } + + diskinfo0_t *di = buffer; + di->validbytes = sizeof( diskinfo0_t ); + di->disktype = DISK_TYPE_SD; + di->sectorsize = 2; + di->sectorcount = capacity; + + DBG_SD printf( "card capacity: %lu sectors\n", capacity ); + return RES_OK; +} +DRESULT disk_getinfo( BYTE drv, BYTE page, void *buffer ) __attribute__ ( ( weak, alias( "sdn_getinfo" ) ) ); + +DRESULT sdn_write( BYTE drv, const BYTE *buffer, DWORD sector, BYTE count ) +{ + uint8_t sec; + uint8_t *buf = ( uint8_t * )buffer; + + if ( drv >= MAX_CARDS ) + { + return RES_NOTRDY; + } + + if ( sdn_status( drv ) & STA_NODISK ) + { + return RES_NOTRDY; + } + + writeled( 1 ); + + for ( sec = 0; sec < count; sec++ ) + { + write_block( sector + sec, buf ); + buf += 512; + } + + writeled( 0 ); + return RES_OK; +} + +DRESULT disk_write( BYTE drv, const BYTE *buffer, DWORD sector, BYTE count ) __attribute__ ( ( weak, + alias( "sdn_write" ) ) ); /* Detect changes of SD card 0 */ -void sdn_changed() { - if (sd_changed) { - DBG_SD printf("ch "); - if(SDCARD_DETECT) { - disk_state = DISK_CHANGED; - } else { - disk_state = DISK_REMOVED; +void sdn_changed() +{ + if ( sd_changed ) + { + DBG_SD printf( "ch " ); + + if ( SDCARD_DETECT ) + { + disk_state = DISK_CHANGED; + } + else + { + disk_state = DISK_REMOVED; + } + + sd_changed = 0; } - sd_changed = 0; - } } diff --git a/src/bootldr/timer.c b/src/bootldr/timer.c index 23da24d..1471d6f 100644 --- a/src/bootldr/timer.c +++ b/src/bootldr/timer.c @@ -1,5 +1,4 @@ /* ___INGO___ */ - #include #include "bits.h" #include "config.h" @@ -18,41 +17,44 @@ extern volatile int sd_changed; volatile tick_t ticks; volatile int wokefromrit; -void timer_init(void) { - /* turn on power to RIT */ - BITBAND(LPC_SC->PCONP, PCRIT) = 1; +void timer_init( void ) +{ + /* turn on power to RIT */ + BITBANG( LPC_SC->PCONP, PCRIT ) = 1; - /* clear RIT mask */ - LPC_RIT->RIMASK = 0; /*xffffffff;*/ + /* clear RIT mask */ + LPC_RIT->RIMASK = 0; /*xffffffff;*/ - /* PCLK = CCLK */ - BITBAND(LPC_SC->PCLKSEL1, 26) = 1; - BITBAND(LPC_SC->PCLKSEL1, PCLK_TIMER3) = 1; + /* PCLK = CCLK */ + BITBANG( LPC_SC->PCLKSEL1, 26 ) = 1; + BITBANG( LPC_SC->PCLKSEL1, PCLK_TIMER3 ) = 1; } -void delay_us(unsigned int time) { - /* Prepare RIT */ - LPC_RIT->RICOUNTER = 0; - LPC_RIT->RICOMPVAL = (CONFIG_CPU_FREQUENCY / 1000000) * time; - LPC_RIT->RICTRL = BV(RITEN) | BV(RITINT); +void delay_us( unsigned int time ) +{ + /* Prepare RIT */ + LPC_RIT->RICOUNTER = 0; + LPC_RIT->RICOMPVAL = ( CONFIG_CPU_FREQUENCY / 1000000 ) * time; + LPC_RIT->RICTRL = BV( RITEN ) | BV( RITINT ); - /* Wait until RIT signals an interrupt */ - while (!(BITBAND(LPC_RIT->RICTRL, RITINT))) ; + /* Wait until RIT signals an interrupt */ + while ( !( BITBANG( LPC_RIT->RICTRL, RITINT ) ) ) ; - /* Disable RIT */ - LPC_RIT->RICTRL = 0; + /* Disable RIT */ + LPC_RIT->RICTRL = 0; } -void delay_ms(unsigned int time) { - /* Prepare RIT */ - LPC_RIT->RICOUNTER = 0; - LPC_RIT->RICOMPVAL = (CONFIG_CPU_FREQUENCY / 1000) * time; - LPC_RIT->RICTRL = BV(RITEN) | BV(RITINT); +void delay_ms( unsigned int time ) +{ + /* Prepare RIT */ + LPC_RIT->RICOUNTER = 0; + LPC_RIT->RICOMPVAL = ( CONFIG_CPU_FREQUENCY / 1000 ) * time; + LPC_RIT->RICTRL = BV( RITEN ) | BV( RITINT ); - /* Wait until RIT signals an interrupt */ - while (!(BITBAND(LPC_RIT->RICTRL, RITINT))) ; + /* Wait until RIT signals an interrupt */ + while ( !( BITBANG( LPC_RIT->RICTRL, RITINT ) ) ) ; - /* Disable RIT */ - LPC_RIT->RICTRL = 0; + /* Disable RIT */ + LPC_RIT->RICTRL = 0; } diff --git a/src/bootldr/timer.h b/src/bootldr/timer.h index f775015..30814b8 100644 --- a/src/bootldr/timer.h +++ b/src/bootldr/timer.h @@ -13,8 +13,9 @@ extern volatile tick_t ticks; * * This inline function returns the current system tick count. */ -static inline tick_t getticks(void) { - return ticks; +static inline tick_t getticks( void ) +{ + return ticks; } #define MS_TO_TICKS(x) (x/10) @@ -35,17 +36,17 @@ static inline tick_t getticks(void) { * (">=0" refers to the time_after_eq macro which wasn't copied) */ #define time_after(a,b) \ - ((int)(b) - (int)(a) < 0) + ((int)(b) - (int)(a) < 0) #define time_before(a,b) time_after(b,a) -void timer_init(void); +void timer_init( void ); /* delay for "time" microseconds - uses the RIT */ -void delay_us(unsigned int time); +void delay_us( unsigned int time ); /* delay for "time" milliseconds - uses the RIT */ -void delay_ms(unsigned int time); -void sleep_ms(unsigned int time); +void delay_ms( unsigned int time ); +void sleep_ms( unsigned int time ); #endif diff --git a/src/bootldr/uart.c b/src/bootldr/uart.c index 611e35c..3eb3b54 100644 --- a/src/bootldr/uart.c +++ b/src/bootldr/uart.c @@ -75,128 +75,179 @@ } */ //static char txbuf[1 << CONFIG_UART_TX_BUF_SHIFT]; -static volatile unsigned int read_idx,write_idx; +static volatile unsigned int read_idx, write_idx; -void uart_putc(char c) { - if (c == '\n') - uart_putc('\r'); - while(!(UART_REGS->LSR & (0x20))); - UART_REGS->THR = c; +void uart_putc( char c ) +{ + if ( c == '\n' ) + { + uart_putc( '\r' ); + } + + while ( !( UART_REGS->LSR & ( 0x20 ) ) ); + + UART_REGS->THR = c; } /* Polling version only */ -unsigned char uart_getc(void) { - /* wait for character */ - while (!(BITBAND(UART_REGS->LSR, 0))) ; - return UART_REGS->RBR; +unsigned char uart_getc( void ) +{ + /* wait for character */ + while ( !( BITBANG( UART_REGS->LSR, 0 ) ) ) ; + + return UART_REGS->RBR; } /* Returns true if a char is ready */ -unsigned char uart_gotc(void) { - return BITBAND(UART_REGS->LSR, 0); +unsigned char uart_gotc( void ) +{ + return BITBANG( UART_REGS->LSR, 0 ); } -void uart_init(void) { - uint32_t div; +void uart_init( void ) +{ + uint32_t div; - /* Turn on power to UART */ - BITBAND(LPC_SC->PCONP, UART_PCONBIT) = 1; + /* Turn on power to UART */ + BITBANG( LPC_SC->PCONP, UART_PCONBIT ) = 1; - /* UART clock = CPU clock - this block is reduced at compile-time */ - if (CONFIG_UART_PCLKDIV == 1) { - BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1; - BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 0; - } else if (CONFIG_UART_PCLKDIV == 2) { - BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0; - BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 1; - } else if (CONFIG_UART_PCLKDIV == 4) { - BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0; - BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 0; - } else { // Fallback: Divide by 8 - BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1; - BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 1; - } + /* UART clock = CPU clock - this block is reduced at compile-time */ + if ( CONFIG_UART_PCLKDIV == 1 ) + { + BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1; + BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 0; + } + else if ( CONFIG_UART_PCLKDIV == 2 ) + { + BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0; + BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 1; + } + else if ( CONFIG_UART_PCLKDIV == 4 ) + { + BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0; + BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 0; + } + else // Fallback: Divide by 8 + { + BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1; + BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 1; + } - /* set baud rate - no fractional stuff for now */ - UART_REGS->LCR = BV(7) | 3; // always 8n1 - div = 0xF80022; //0x850004; // baud2divisor(CONFIG_UART_BAUDRATE); + /* set baud rate - no fractional stuff for now */ + UART_REGS->LCR = BV( 7 ) | 3; // always 8n1 + div = 0xF80022; //0x850004; // baud2divisor(CONFIG_UART_BAUDRATE); - UART_REGS->DLL = div & 0xff; - UART_REGS->DLM = (div >> 8) & 0xff; - BITBAND(UART_REGS->LCR, 7) = 0; + UART_REGS->DLL = div & 0xff; + UART_REGS->DLM = ( div >> 8 ) & 0xff; + BITBANG( UART_REGS->LCR, 7 ) = 0; - if (div & 0xff0000) { - UART_REGS->FDR = (div >> 16) & 0xff; - } + if ( div & 0xff0000 ) + { + UART_REGS->FDR = ( div >> 16 ) & 0xff; + } - /* reset and enable FIFO */ - UART_REGS->FCR = BV(0); + /* reset and enable FIFO */ + UART_REGS->FCR = BV( 0 ); - UART_REGS->THR = '?'; + UART_REGS->THR = '?'; } /* --- generic code below --- */ -void uart_puthex(uint8_t num) { - uint8_t tmp; - tmp = (num & 0xf0) >> 4; - if (tmp < 10) - uart_putc('0'+tmp); - else - uart_putc('a'+tmp-10); +void uart_puthex( uint8_t num ) +{ + uint8_t tmp; + tmp = ( num & 0xf0 ) >> 4; - tmp = num & 0x0f; - if (tmp < 10) - uart_putc('0'+tmp); - else - uart_putc('a'+tmp-10); -} - -void uart_trace(void *ptr, uint16_t start, uint16_t len) { - uint16_t i; - uint8_t j; - uint8_t ch; - uint8_t *data = ptr; - - data+=start; - for(i=0;i>8); - uart_puthex(start&0xff); - uart_putc('|'); - uart_putc(' '); - for(j=0;j<16;j++) { - if(i+j0x7e) - ch='.'; - uart_putc(ch); - } else { - uart_putc(' '); - } + else + { + uart_putc( 'a' + tmp - 10 ); + } + + tmp = num & 0x0f; + + if ( tmp < 10 ) + { + uart_putc( '0' + tmp ); + } + else + { + uart_putc( 'a' + tmp - 10 ); } - uart_putc('|'); - uart_putcrlf(); - start+=16; - } } -void uart_flush(void) { - while (read_idx != write_idx) ; +void uart_trace( void *ptr, uint16_t start, uint16_t len ) +{ + uint16_t i; + uint8_t j; + uint8_t ch; + uint8_t *data = ptr; + + data += start; + + for ( i = 0; i < len; i += 16 ) + { + + uart_puthex( start >> 8 ); + uart_puthex( start & 0xff ); + uart_putc( '|' ); + uart_putc( ' ' ); + + for ( j = 0; j < 16; j++ ) + { + if ( i + j < len ) + { + ch = *( data + j ); + uart_puthex( ch ); + } + else + { + uart_putc( ' ' ); + uart_putc( ' ' ); + } + + uart_putc( ' ' ); + } + + uart_putc( '|' ); + + for ( j = 0; j < 16; j++ ) + { + if ( i + j < len ) + { + ch = *( data++ ); + + if ( ch < 32 || ch > 0x7e ) + { + ch = '.'; + } + + uart_putc( ch ); + } + else + { + uart_putc( ' ' ); + } + } + + uart_putc( '|' ); + uart_putcrlf(); + start += 16; + } } -void uart_puts(const char *text) { - while (*text) { - uart_putc(*text++); - } +void uart_flush( void ) +{ + while ( read_idx != write_idx ) ; +} + +void uart_puts( const char *text ) +{ + while ( *text ) + { + uart_putc( *text++ ); + } } diff --git a/src/bootldr/uart.h b/src/bootldr/uart.h index 93f4ed3..016c273 100644 --- a/src/bootldr/uart.h +++ b/src/bootldr/uart.h @@ -16,21 +16,21 @@ #ifdef __AVR__ # include - void uart_puts_P(prog_char *text); +void uart_puts_P( prog_char *text ); #else # define uart_puts_P(str) uart_puts(str) #endif -void uart_init(void); -unsigned char uart_getc(void); -unsigned char uart_gotc(void); -void uart_putc(char c); -void uart_puts(const char *str); -void uart_puthex(uint8_t num); -void uart_trace(void *ptr, uint16_t start, uint16_t len); -void uart_flush(void); -int printf(const char *fmt, ...); -int snprintf(char *str, size_t size, const char *format, ...); +void uart_init( void ); +unsigned char uart_getc( void ); +unsigned char uart_gotc( void ); +void uart_putc( char c ); +void uart_puts( const char *str ); +void uart_puthex( uint8_t num ); +void uart_trace( void *ptr, uint16_t start, uint16_t len ); +void uart_flush( void ); +int printf( const char *fmt, ... ); +int snprintf( char *str, size_t size, const char *format, ... ); #define uart_putcrlf() uart_putc('\n') /* A few symbols to make this code work for all four UARTs */ diff --git a/src/ccsbcs.c b/src/ccsbcs.c index eb0ab4e..75f4ecd 100644 --- a/src/ccsbcs.c +++ b/src/ccsbcs.c @@ -31,463 +31,484 @@ #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 +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, 0xO650, 0x2248, - 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +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, 0xO650, 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 +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 == 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 +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 +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 +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 +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 +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 == 858 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP858(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, 0x2550, 0x00A2, 0x00A5, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, - 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x20AC, 0x00CD, 0x00CE, - 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00C6, 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 +const WCHAR Tbl[] = /* CP858(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, 0x2550, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x20AC, 0x00CD, 0x00CE, + 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00C6, 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 == 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 +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 == 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 +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 == 874 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP874(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, - 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, - 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, - 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F, - 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, - 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, - 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, - 0x0E38, 0x0E39, 0x0E3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E3F, - 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, - 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, - 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, - 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000, 0x0000, 0x0000 +const WCHAR Tbl[] = /* CP874(0x80-0xFF) to Unicode conversion table */ +{ + 0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, + 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, + 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, + 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F, + 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, + 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, + 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, + 0x0E38, 0x0E39, 0x0E3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E3F, + 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, + 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, + 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, + 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000, 0x0000, 0x0000 }; #elif _CODE_PAGE == 1250 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP1250(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, - 0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A, - 0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B, - 0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C, - 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, - 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, - 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, - 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, - 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, - 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, - 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, - 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9 +const WCHAR Tbl[] = /* CP1250(0x80-0xFF) to Unicode conversion table */ +{ + 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, + 0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A, + 0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B, + 0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C, + 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, + 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, + 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, + 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, + 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, + 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, + 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, + 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9 }; #elif _CODE_PAGE == 1251 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP1251(0x80-0xFF) to Unicode conversion table */ - 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, - 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, - 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x2111, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, - 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, - 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407, - 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, - 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457, - 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, - 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, - 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F +const WCHAR Tbl[] = /* CP1251(0x80-0xFF) to Unicode conversion table */ +{ + 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, + 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, + 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2111, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, + 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, + 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407, + 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, + 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457, + 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, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F }; #elif _CODE_PAGE == 1252 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, - 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF +const WCHAR Tbl[] = /* CP1252(0x80-0xFF) to Unicode conversion table */ +{ + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF }; #elif _CODE_PAGE == 1253 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP1253(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x0000, 0x2030, 0x0000, 0x2039, 0x000C, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x0000, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7, - 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, - 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, - 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, - 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, - 0x03A8, 0x03A9, 0x03AA, 0x03AD, 0x03AC, 0x03AD, 0x03AE, 0x03AF, - 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, - 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, - 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, - 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000 +const WCHAR Tbl[] = /* CP1253(0x80-0xFF) to Unicode conversion table */ +{ + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x0000, 0x2030, 0x0000, 0x2039, 0x000C, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x0000, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7, + 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, + 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, + 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, + 0x03A8, 0x03A9, 0x03AA, 0x03AD, 0x03AC, 0x03AD, 0x03AE, 0x03AF, + 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, + 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, + 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000 }; #elif _CODE_PAGE == 1254 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP1254(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x210A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, - 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00BD, 0x00DC, 0x0130, 0x015E, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF +const WCHAR Tbl[] = /* CP1254(0x80-0xFF) to Unicode conversion table */ +{ + 0x20AC, 0x0000, 0x210A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00BD, 0x00DC, 0x0130, 0x015E, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF }; #elif _CODE_PAGE == 1255 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP1255(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, - 0x05B8, 0x05B9, 0x0000, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, - 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3, - 0x05F4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 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, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000 +const WCHAR Tbl[] = /* CP1255(0x80-0xFF) to Unicode conversion table */ +{ + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, + 0x05B8, 0x05B9, 0x0000, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, + 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3, + 0x05F4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 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, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000 }; #elif _CODE_PAGE == 1256 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP1256(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, - 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA, - 0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F, - 0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, - 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, - 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7, - 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0640, 0x0642, 0x0643, - 0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF, - 0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7, - 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2 +const WCHAR Tbl[] = /* CP1256(0x80-0xFF) to Unicode conversion table */ +{ + 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, + 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA, + 0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F, + 0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, + 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, + 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7, + 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0640, 0x0642, 0x0643, + 0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF, + 0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7, + 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2 } #elif _CODE_PAGE == 1257 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP1257(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, - 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x00AF, 0x02DB, 0x0000, - 0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x0000, 0x00A6, 0x00A7, - 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, - 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, - 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, - 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, - 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, - 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, - 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, - 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, - 0x0173, 0x014E, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9 +const WCHAR Tbl[] = /* CP1257(0x80-0xFF) to Unicode conversion table */ +{ + 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, + 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x00AF, 0x02DB, 0x0000, + 0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x0000, 0x00A6, 0x00A7, + 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, + 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, + 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, + 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, + 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, + 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, + 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, + 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, + 0x0173, 0x014E, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9 }; #elif _CODE_PAGE == 1258 #define _TBLDEF 1 static -const WCHAR Tbl[] = { /* CP1258(0x80-0xFF) to Unicode conversion table */ - 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, - 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0x0000, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF, - 0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF, - 0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF +const WCHAR Tbl[] = /* CP1258(0x80-0xFF) to Unicode conversion table */ +{ + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0000, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF, + 0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF, + 0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF }; #endif @@ -498,43 +519,54 @@ const WCHAR Tbl[] = { /* CP1258(0x80-0xFF) to Unicode conversion table */ #endif -WCHAR ff_convert ( /* Converted character, Returns zero on error */ - WCHAR src, /* Character code to be converted */ - UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */ +WCHAR ff_convert ( /* Converted character, Returns zero on error */ + WCHAR src, /* Character code to be converted */ + UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */ ) { - WCHAR c; + WCHAR c; - if (src < 0x80) { /* ASCII */ - c = src; + if ( src < 0x80 ) /* ASCII */ + { + c = src; - } else { - if (dir) { /* OEMCP to Unicode */ - c = (src >= 0x100) ? 0 : Tbl[src - 0x80]; + } + else + { + if ( dir ) /* OEMCP to Unicode */ + { + c = ( src >= 0x100 ) ? 0 : Tbl[src - 0x80]; - } else { /* Unicode to OEMCP */ - for (c = 0; c < 0x80; c++) { - if (src == Tbl[c]) break; - } - c = (c + 0x80) & 0xFF; - } - } + } + else /* Unicode to OEMCP */ + { + for ( c = 0; c < 0x80; c++ ) + { + if ( src == Tbl[c] ) + { + break; + } + } - return c; + c = ( c + 0x80 ) & 0xFF; + } + } + + return c; } -WCHAR ff_wtoupper ( /* Upper converted character */ - WCHAR chr /* Input character */ +WCHAR ff_wtoupper ( /* Upper converted character */ + WCHAR chr /* Input character */ ) { - static const WCHAR tbl_lower[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x0FF, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, 0x192, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0 }; - static const WCHAR tbl_upper[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, 0x191, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0 }; - int i; + static const WCHAR tbl_lower[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x0FF, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, 0x192, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0 }; + static const WCHAR tbl_upper[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, 0x191, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0 }; + int i; - for (i = 0; tbl_lower[i] && chr != tbl_lower[i]; i++) ; + for ( i = 0; tbl_lower[i] && chr != tbl_lower[i]; i++ ) ; - return tbl_lower[i] ? tbl_upper[i] : chr; + return tbl_lower[i] ? tbl_upper[i] : chr; } diff --git a/src/cfg.c b/src/cfg.c index 3d05599..40af440 100644 --- a/src/cfg.c +++ b/src/cfg.c @@ -3,57 +3,70 @@ #include "uart.h" #include "fileops.h" -cfg_t CFG = { - .cfg_ver_maj = 1, - .cfg_ver_min = 0, - .last_game_valid = 0, - .vidmode_menu = VIDMODE_AUTO, - .vidmode_game = VIDMODE_AUTO, - .pair_mode_allowed = 0, - .bsx_use_systime = 0, - .bsx_time = 0x0619970301180530LL +cfg_t CFG = +{ + .cfg_ver_maj = 1, + .cfg_ver_min = 0, + .last_game_valid = 0, + .vidmode_menu = VIDMODE_AUTO, + .vidmode_game = VIDMODE_AUTO, + .pair_mode_allowed = 0, + .bsx_use_systime = 0, + .bsx_time = 0x0619970301180530LL }; -int cfg_save() { - int err = 0; - file_open(CFG_FILE, FA_CREATE_ALWAYS | FA_WRITE); - if(file_writeblock(&CFG, 0, sizeof(CFG)) < sizeof(CFG)) { - err = file_res; - } - file_close(); - return err; +int cfg_save() +{ + int err = 0; + file_open( CFG_FILE, FA_CREATE_ALWAYS | FA_WRITE ); + + if ( file_writeblock( &CFG, 0, sizeof( CFG ) ) < sizeof( CFG ) ) + { + err = file_res; + } + + file_close(); + return err; } -int cfg_load() { - int err = 0; - file_open(CFG_FILE, FA_READ); - if(file_readblock(&CFG, 0, sizeof(CFG)) < sizeof(CFG)) { - err = file_res; - } - file_close(); - return err; +int cfg_load() +{ + int err = 0; + file_open( CFG_FILE, FA_READ ); + + if ( file_readblock( &CFG, 0, sizeof( CFG ) ) < sizeof( CFG ) ) + { + err = file_res; + } + + file_close(); + return err; } -int cfg_save_last_game(uint8_t *fn) { - int err = 0; - file_open(LAST_FILE, FA_CREATE_ALWAYS | FA_WRITE); - err = f_puts((const TCHAR*)fn, &file_handle); - file_close(); - return err; +int cfg_save_last_game( uint8_t *fn ) +{ + int err = 0; + file_open( LAST_FILE, FA_CREATE_ALWAYS | FA_WRITE ); + err = f_puts( ( const TCHAR * )fn, &file_handle ); + file_close(); + return err; } -int cfg_get_last_game(uint8_t *fn) { - int err = 0; - file_open(LAST_FILE, FA_READ); - f_gets((TCHAR*)fn, 255, &file_handle); - file_close(); - return err; +int cfg_get_last_game( uint8_t *fn ) +{ + int err = 0; + file_open( LAST_FILE, FA_READ ); + f_gets( ( TCHAR * )fn, 255, &file_handle ); + file_close(); + return err; } -void cfg_set_last_game_valid(uint8_t valid) { - CFG.last_game_valid = valid; +void cfg_set_last_game_valid( uint8_t valid ) +{ + CFG.last_game_valid = valid; } -uint8_t cfg_is_last_game_valid() { - return CFG.last_game_valid; +uint8_t cfg_is_last_game_valid() +{ + return CFG.last_game_valid; } diff --git a/src/cfg.h b/src/cfg.h index f45eabe..5d53294 100644 --- a/src/cfg.h +++ b/src/cfg.h @@ -6,34 +6,36 @@ #define CFG_FILE ((const uint8_t*)"/sd2snes/sd2snes.cfg") #define LAST_FILE ((const uint8_t*)"/sd2snes/lastgame.cfg") -typedef enum { - VIDMODE_AUTO = 0, - VIDMODE_60, - VIDMODE_50 +typedef enum +{ + VIDMODE_AUTO = 0, + VIDMODE_60, + VIDMODE_50 } cfg_vidmode_t; -typedef struct _cfg_block { - uint8_t cfg_ver_maj; - uint8_t cfg_ver_min; - uint8_t last_game_valid; - uint8_t vidmode_menu; - uint8_t vidmode_game; - uint8_t pair_mode_allowed; - uint8_t bsx_use_systime; - uint64_t bsx_time; +typedef struct _cfg_block +{ + uint8_t cfg_ver_maj; + uint8_t cfg_ver_min; + uint8_t last_game_valid; + uint8_t vidmode_menu; + uint8_t vidmode_game; + uint8_t pair_mode_allowed; + uint8_t bsx_use_systime; + uint64_t bsx_time; } cfg_t; -int cfg_save(void); -int cfg_load(void); +int cfg_save( void ); +int cfg_load( void ); -int cfg_save_last_game(uint8_t *fn); -int cfg_get_last_game(uint8_t *fn); +int cfg_save_last_game( uint8_t *fn ); +int cfg_get_last_game( uint8_t *fn ); -cfg_vidmode_t cfg_get_vidmode_menu(void); -cfg_vidmode_t cfg_get_vidmode_game(void); +cfg_vidmode_t cfg_get_vidmode_menu( void ); +cfg_vidmode_t cfg_get_vidmode_game( void ); -void cfg_set_last_game_valid(uint8_t); -uint8_t cfg_is_last_game_valid(void); -uint8_t cfg_is_pair_mode_allowed(void); +void cfg_set_last_game_valid( uint8_t ); +uint8_t cfg_is_last_game_valid( void ); +uint8_t cfg_is_pair_mode_allowed( void ); #endif diff --git a/src/cic.c b/src/cic.c index efb0d11..afa1679 100644 --- a/src/cic.c +++ b/src/cic.c @@ -7,74 +7,108 @@ char *cicstatenames[4] = { "CIC_OK", "CIC_FAIL", "CIC_PAIR", "CIC_SCIC" }; char *cicstatefriendly[4] = {"Original or no CIC", "Original CIC(failed)", "SuperCIC enhanced", "SuperCIC detected, not used"}; -void print_cic_state() { - printf("CIC state: %s\n", get_cic_statename(get_cic_state())); +void print_cic_state() +{ + printf( "CIC state: %s\n", get_cic_statename( get_cic_state() ) ); } -inline char *get_cic_statefriendlyname(enum cicstates state) { - return cicstatefriendly[state]; +inline char *get_cic_statefriendlyname( enum cicstates state ) +{ + return cicstatefriendly[state]; } -inline char *get_cic_statename(enum cicstates state) { - return cicstatenames[state]; +inline char *get_cic_statename( enum cicstates state ) +{ + return cicstatenames[state]; } -enum cicstates get_cic_state() { - uint32_t count; - uint32_t togglecount = 0; - uint8_t state, state_old; +enum cicstates get_cic_state() +{ + uint32_t count; + uint32_t togglecount = 0; + uint8_t state, state_old; - state_old = BITBAND(SNES_CIC_STATUS_REG->FIOPIN, SNES_CIC_STATUS_BIT); -/* this loop samples at ~10MHz */ - for(count=0; countFIOPIN, SNES_CIC_STATUS_BIT); - if(state != state_old) { - togglecount++; + state_old = BITBAND( SNES_CIC_STATUS_REG->FIOPIN, SNES_CIC_STATUS_BIT ); + + /* this loop samples at ~10MHz */ + for ( count = 0; count < CIC_SAMPLECOUNT; count++ ) + { + state = BITBAND( SNES_CIC_STATUS_REG->FIOPIN, SNES_CIC_STATUS_BIT ); + + if ( state != state_old ) + { + togglecount++; + } + + state_old = state; + } + + printf( "%ld\n", togglecount ); + + /* CIC_TOGGLE_THRESH_PAIR > CIC_TOGGLE_THRESH_SCIC */ + if ( togglecount > CIC_TOGGLE_THRESH_PAIR ) + { + return CIC_PAIR; + } + else if ( togglecount > CIC_TOGGLE_THRESH_SCIC ) + { + return CIC_SCIC; + } + else if ( state ) + { + return CIC_OK; + } + else + { + return CIC_FAIL; } - state_old = state; - } - printf("%ld\n", togglecount); -/* CIC_TOGGLE_THRESH_PAIR > CIC_TOGGLE_THRESH_SCIC */ - if(togglecount > CIC_TOGGLE_THRESH_PAIR) { - return CIC_PAIR; - } else if(togglecount > CIC_TOGGLE_THRESH_SCIC) { - return CIC_SCIC; - } else if(state) { - return CIC_OK; - } else return CIC_FAIL; } -void cic_init(int allow_pairmode) { - BITBAND(SNES_CIC_PAIR_REG->FIODIR, SNES_CIC_PAIR_BIT) = 1; - if(allow_pairmode) { - BITBAND(SNES_CIC_PAIR_REG->FIOCLR, SNES_CIC_PAIR_BIT) = 1; - } else { - BITBAND(SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT) = 1; - } +void cic_init( int allow_pairmode ) +{ + BITBAND( SNES_CIC_PAIR_REG->FIODIR, SNES_CIC_PAIR_BIT ) = 1; + + if ( allow_pairmode ) + { + BITBAND( SNES_CIC_PAIR_REG->FIOCLR, SNES_CIC_PAIR_BIT ) = 1; + } + else + { + BITBAND( SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT ) = 1; + } } /* prepare GPIOs for pair mode + set initial modes */ -void cic_pair(int init_vmode, int init_d4) { - cic_videomode(init_vmode); - cic_d4(init_d4); +void cic_pair( int init_vmode, int init_d4 ) +{ + cic_videomode( init_vmode ); + cic_d4( init_d4 ); - BITBAND(SNES_CIC_D0_REG->FIODIR, SNES_CIC_D0_BIT) = 1; - BITBAND(SNES_CIC_D1_REG->FIODIR, SNES_CIC_D1_BIT) = 1; + BITBAND( SNES_CIC_D0_REG->FIODIR, SNES_CIC_D0_BIT ) = 1; + BITBAND( SNES_CIC_D1_REG->FIODIR, SNES_CIC_D1_BIT ) = 1; } -void cic_videomode(int value) { - if(value) { - BITBAND(SNES_CIC_D0_REG->FIOSET, SNES_CIC_D0_BIT) = 1; - } else { - BITBAND(SNES_CIC_D0_REG->FIOCLR, SNES_CIC_D0_BIT) = 1; - } +void cic_videomode( int value ) +{ + if ( value ) + { + BITBAND( SNES_CIC_D0_REG->FIOSET, SNES_CIC_D0_BIT ) = 1; + } + else + { + BITBAND( SNES_CIC_D0_REG->FIOCLR, SNES_CIC_D0_BIT ) = 1; + } } -void cic_d4(int value) { - if(value) { - BITBAND(SNES_CIC_D1_REG->FIOSET, SNES_CIC_D1_BIT) = 1; - } else { - BITBAND(SNES_CIC_D1_REG->FIOCLR, SNES_CIC_D1_BIT) = 1; - } +void cic_d4( int value ) +{ + if ( value ) + { + BITBAND( SNES_CIC_D1_REG->FIOSET, SNES_CIC_D1_BIT ) = 1; + } + else + { + BITBAND( SNES_CIC_D1_REG->FIOCLR, SNES_CIC_D1_BIT ) = 1; + } } diff --git a/src/cic.h b/src/cic.h index 23fd767..321f754 100644 --- a/src/cic.h +++ b/src/cic.h @@ -1,9 +1,9 @@ #ifndef _CIC_H #define _CIC_H -#define CIC_SAMPLECOUNT (100000) -#define CIC_TOGGLE_THRESH_PAIR (2500) -#define CIC_TOGGLE_THRESH_SCIC (10) +#define CIC_SAMPLECOUNT (100000) +#define CIC_TOGGLE_THRESH_PAIR (2500) +#define CIC_TOGGLE_THRESH_SCIC (10) #include #include "bits.h" @@ -11,14 +11,14 @@ enum cicstates { CIC_OK = 0, CIC_FAIL, CIC_PAIR, CIC_SCIC }; enum cic_region { CIC_NTSC = 0, CIC_PAL }; -void print_cic_state(void); -char *get_cic_statename(enum cicstates state); -char *get_cic_statefriendlyname(enum cicstates state); -enum cicstates get_cic_state(void); -void cic_init(int allow_pairmode); +void print_cic_state( void ); +char *get_cic_statename( enum cicstates state ); +char *get_cic_statefriendlyname( enum cicstates state ); +enum cicstates get_cic_state( void ); +void cic_init( int allow_pairmode ); -void cic_pair(int init_vmode, int init_d4); -void cic_videomode(int value); -void cic_d4(int value); +void cic_pair( int init_vmode, int init_d4 ); +void cic_videomode( int value ); +void cic_d4( int value ); #endif diff --git a/src/cli.c b/src/cli.c index 8bbd1b9..e436539 100644 --- a/src/cli.c +++ b/src/cli.c @@ -42,6 +42,7 @@ #include "fileops.h" #include "memory.h" #include "snes.h" +#include "tests.h" #include "fpga.h" #include "fpga_spi.h" #include "cic.h" @@ -53,163 +54,216 @@ #define MAX_LINE 250 /* Variables */ -static char cmdbuffer[MAX_LINE+1]; +static char cmdbuffer[MAX_LINE + 1]; static char *curchar; /* Word lists */ static char command_words[] = - "cd\0reset\0sreset\0dir\0ls\0test\0exit\0loadrom\0loadraw\0saveraw\0put\0rm\0mkdir\0d4\0vmode\0mapper\0settime\0time\0setfeature\0hexdump\0w8\0w16\0memset\0"; -enum { CMD_CD = 0, CMD_RESET, CMD_SRESET, CMD_DIR, CMD_LS, CMD_TEST, CMD_EXIT, CMD_LOADROM, CMD_LOADRAW, CMD_SAVERAW, CMD_PUT, CMD_RM, CMD_MKDIR, CMD_D4, CMD_VMODE, CMD_MAPPER, CMD_SETTIME, CMD_TIME, CMD_SETFEATURE, CMD_HEXDUMP, CMD_W8, CMD_W16, CMD_MEMSET }; + "cd\0reset\0sreset\0dir\0ls\0test\0exit\0loadrom\0loadraw\0saveraw\0put\0rm\0mkdir\0d4\0vmode\0mapper\0settime\0time\0setfeature\0hexdump\0w8\0w16\0memset\0memtest\0"; +enum { CMD_CD = 0, CMD_RESET, CMD_SRESET, CMD_DIR, CMD_LS, CMD_TEST, CMD_EXIT, CMD_LOADROM, CMD_LOADRAW, CMD_SAVERAW, CMD_PUT, CMD_RM, CMD_MKDIR, CMD_D4, CMD_VMODE, CMD_MAPPER, CMD_SETTIME, CMD_TIME, CMD_SETFEATURE, CMD_HEXDUMP, CMD_W8, CMD_W16, CMD_MEMSET, CMD_MEMTEST }; /* ------------------------------------------------------------------------- */ /* Parse functions */ /* ------------------------------------------------------------------------- */ /* Skip spaces at curchar */ -static uint8_t skip_spaces(void) { - uint8_t res = (*curchar == ' ' || *curchar == 0); +static uint8_t skip_spaces( void ) +{ + uint8_t res = ( *curchar == ' ' || *curchar == 0 ); - while (*curchar == ' ') - curchar++; + while ( *curchar == ' ' ) + { + curchar++; + } - return res; + return res; } /* Parse the string in curchar for an integer with bounds [lower,upper] */ -static int32_t parse_unsigned(uint32_t lower, uint32_t upper, uint8_t base) { - char *end; - uint32_t result; +static int32_t parse_unsigned( uint32_t lower, uint32_t upper, uint8_t base ) +{ + char *end; + uint32_t result; - if (strlen(curchar) == 1 && *curchar == '?') { - printf("Number between %ld[0x%lx] and %ld[0x%lx] expected\n",lower,lower,upper,upper); - return -2; - } + if ( strlen( curchar ) == 1 && *curchar == '?' ) + { + printf( "Number between %ld[0x%lx] and %ld[0x%lx] expected\n", lower, lower, upper, upper ); + return -2; + } - result = strtoul(curchar, &end, base); - if ((*end != ' ' && *end != 0) || errno != 0) { - printf("Invalid numeric argument\n"); - return -1; - } + result = strtoul( curchar, &end, base ); - curchar = end; - skip_spaces(); + if ( ( *end != ' ' && *end != 0 ) || errno != 0 ) + { + printf( "Invalid numeric argument\n" ); + return -1; + } - if (result < lower || result > upper) { - printf("Numeric argument out of range (%ld..%ld)\n",lower,upper); - return -1; - } + curchar = end; + skip_spaces(); - return result; + if ( result < lower || result > upper ) + { + printf( "Numeric argument out of range (%ld..%ld)\n", lower, upper ); + return -1; + } + + return result; } /* Parse the string starting with curchar for a word in wordlist */ -static int8_t parse_wordlist(char *wordlist) { - uint8_t i, matched; - unsigned char *cur, *ptr; - unsigned char c; +static int8_t parse_wordlist( char *wordlist ) +{ + uint8_t i, matched; + unsigned char *cur, *ptr; + unsigned char c; - i = 0; - ptr = (unsigned char *)wordlist; + i = 0; + ptr = ( unsigned char * )wordlist; - // Command list on "?" - if (strlen(curchar) == 1 && *curchar == '?') { - printf("Commands available: \n "); - while (1) { - c = *ptr++; - if (c == 0) { - if (*ptr == 0) { - printf("\n"); - return -2; - } else { - printf("\n "); + // Command list on "?" + if ( strlen( curchar ) == 1 && *curchar == '?' ) + { + printf( "Commands available: \n " ); + + while ( 1 ) + { + c = *ptr++; + + if ( c == 0 ) + { + if ( *ptr == 0 ) + { + printf( "\n" ); + return -2; + } + else + { + printf( "\n " ); + } + } + else + { + uart_putc( c ); + } } - } else - uart_putc(c); } - } - while (1) { - cur = (unsigned char *)curchar; - matched = 1; - c = *ptr; - do { - // If current word list character is \0: No match found - if (c == 0) { - printf("Unknown word: %s\n(use ? for help)",curchar); - return -1; - } + while ( 1 ) + { + cur = ( unsigned char * )curchar; + matched = 1; + c = *ptr; - if (tolower((int)c) != tolower((int)*cur)) { - // Check for end-of-word - if (cur != (unsigned char*)curchar && (*cur == ' ' || *cur == 0)) { - // Partial match found, return that - break; - } else { - matched = 0; - break; + do + { + // If current word list character is \0: No match found + if ( c == 0 ) + { + printf( "Unknown word: %s\n(use ? for help)", curchar ); + return -1; + } + + if ( tolower( ( int )c ) != tolower( ( int )*cur ) ) + { + // Check for end-of-word + if ( cur != ( unsigned char * )curchar && ( *cur == ' ' || *cur == 0 ) ) + { + // Partial match found, return that + break; + } + else + { + matched = 0; + break; + } + } + + ptr++; + cur++; + c = *ptr; } - } - ptr++; - cur++; - c = *ptr; - } while (c != 0); + while ( c != 0 ); - if (matched) { - char *tmp = curchar; + if ( matched ) + { + char *tmp = curchar; - curchar = (char *)cur; - // Return match only if whitespace or end-of-string follows - // (avoids mismatching partial words) - if (skip_spaces()) { - return i; - } else { - printf("Unknown word: %s\n(use ? for help)\n",tmp); - return -1; - } - } else { - // Try next word in list - i++; - while (*ptr++ != 0) ; + curchar = ( char * )cur; + + // Return match only if whitespace or end-of-string follows + // (avoids mismatching partial words) + if ( skip_spaces() ) + { + return i; + } + else + { + printf( "Unknown word: %s\n(use ? for help)\n", tmp ); + return -1; + } + } + else + { + // Try next word in list + i++; + + while ( *ptr++ != 0 ) ; + } } - } } /* Read a line from serial, uses cmdbuffer as storage */ -static char *getline(char *prompt) { - int i=0; - char c; +static char *getline( char *prompt ) +{ + int i = 0; + char c; - printf("\n%s",prompt); - memset(cmdbuffer,0,sizeof(cmdbuffer)); + printf( "\n%s", prompt ); + memset( cmdbuffer, 0, sizeof( cmdbuffer ) ); - while (1) { - c = uart_getc(); - if (c == 13) - break; + while ( 1 ) + { + c = uart_getc(); - if (c == 27 || c == 3) { - printf("\\\n%s",prompt); - i = 0; - memset(cmdbuffer,0,sizeof(cmdbuffer)); - continue; + if ( c == 13 ) + { + break; + } + + if ( c == 27 || c == 3 ) + { + printf( "\\\n%s", prompt ); + i = 0; + memset( cmdbuffer, 0, sizeof( cmdbuffer ) ); + continue; + } + + if ( c == 127 || c == 8 ) + { + if ( i > 0 ) + { + i--; + uart_putc( 8 ); // backspace + uart_putc( ' ' ); // erase character + uart_putc( 8 ); // backspace + } + else + { + continue; + } + } + else + { + if ( i < sizeof( cmdbuffer ) - 1 ) + { + cmdbuffer[i++] = c; + uart_putc( c ); + } + } } - if (c == 127 || c == 8) { - if (i > 0) { - i--; - uart_putc(8); // backspace - uart_putc(' '); // erase character - uart_putc(8); // backspace - } else - continue; - } else { - if (i < sizeof(cmdbuffer)-1) { - cmdbuffer[i++] = c; - uart_putc(c); - } - } - } - cmdbuffer[i] = 0; - return cmdbuffer; + cmdbuffer[i] = 0; + return cmdbuffer; } @@ -218,369 +272,480 @@ static char *getline(char *prompt) { /* ------------------------------------------------------------------------- */ /* Reset */ -static void cmd_reset(void) { - /* force watchdog reset */ - LPC_WDT->WDTC = 256; // minimal timeout - LPC_WDT->WDCLKSEL = BV(31); // internal RC, lock register - LPC_WDT->WDMOD = BV(0) | BV(1); // enable watchdog and reset-by-watchdog - LPC_WDT->WDFEED = 0xaa; - LPC_WDT->WDFEED = 0x55; // initial feed to really enable WDT +static void cmd_reset( void ) +{ + /* force watchdog reset */ + LPC_WDT->WDTC = 256; // minimal timeout + LPC_WDT->WDCLKSEL = BV( 31 ); // internal RC, lock register + LPC_WDT->WDMOD = BV( 0 ) | BV( 1 ); // enable watchdog and reset-by-watchdog + LPC_WDT->WDFEED = 0xaa; + LPC_WDT->WDFEED = 0x55; // initial feed to really enable WDT } /* Show the contents of the current directory */ -static void cmd_show_directory(void) { - FRESULT res; - DIR dh; - FILINFO finfo; - uint8_t *name; +static void cmd_show_directory( void ) +{ + FRESULT res; + DIR dh; + FILINFO finfo; + uint8_t *name; - f_getcwd((TCHAR*)file_lfn, 255); + f_getcwd( ( TCHAR * )file_lfn, 255 ); - res = f_opendir(&dh, (TCHAR*)file_lfn); - if (res != FR_OK) { - printf("f_opendir failed, result %d\n",res); - return; - } + res = f_opendir( &dh, ( TCHAR * )file_lfn ); - finfo.lfname = (TCHAR*)file_lfn; - finfo.lfsize = 255; - - do { - /* Read the next entry */ - res = f_readdir(&dh, &finfo); - if (res != FR_OK) { - printf("f_readdir failed, result %d\n",res); - return; + if ( res != FR_OK ) + { + printf( "f_opendir failed, result %d\n", res ); + return; } - /* Abort if none was found */ - if (!finfo.fname[0]) - break; + finfo.lfname = ( TCHAR * )file_lfn; + finfo.lfsize = 255; - /* Skip volume labels */ - if (finfo.fattrib & AM_VOL) - continue; + do + { + /* Read the next entry */ + res = f_readdir( &dh, &finfo ); - /* Select between LFN and 8.3 name */ - if (finfo.lfname[0]) - name = (uint8_t*)finfo.lfname; - else { - name = (uint8_t*)finfo.fname; - strlwr((char *)name); + if ( res != FR_OK ) + { + printf( "f_readdir failed, result %d\n", res ); + return; + } + + /* Abort if none was found */ + if ( !finfo.fname[0] ) + { + break; + } + + /* Skip volume labels */ + if ( finfo.fattrib & AM_VOL ) + { + continue; + } + + /* Select between LFN and 8.3 name */ + if ( finfo.lfname[0] ) + { + name = ( uint8_t * )finfo.lfname; + } + else + { + name = ( uint8_t * )finfo.fname; + strlwr( ( char * )name ); + } + + printf( "%s [%s] (%ld)", finfo.lfname, finfo.fname, finfo.fsize ); + + /* Directory indicator (Unix-style) */ + if ( finfo.fattrib & AM_DIR ) + { + uart_putc( '/' ); + } + + printf( "\n" ); } - - printf("%s [%s] (%ld)",finfo.lfname, finfo.fname, finfo.fsize); - - /* Directory indicator (Unix-style) */ - if (finfo.fattrib & AM_DIR) - uart_putc('/'); - - printf("\n"); - } while (finfo.fname[0]); + while ( finfo.fname[0] ); } -static void cmd_loadrom(void) { - uint32_t address = 0; - uint8_t flags = LOADROM_WITH_SRAM | LOADROM_WITH_RESET; - load_rom((uint8_t*)curchar, address, flags); +static void cmd_loadrom( void ) +{ + uint32_t address = 0; + uint8_t flags = LOADROM_WITH_SRAM | LOADROM_WITH_RESET; + load_rom( ( uint8_t * )curchar, address, flags ); } -static void cmd_loadraw(void) { - uint32_t address = parse_unsigned(0,16777216,16); - load_sram((uint8_t*)curchar, address); +static void cmd_loadraw( void ) +{ + uint32_t address = parse_unsigned( 0, 16777216, 16 ); + load_sram( ( uint8_t * )curchar, address ); } -static void cmd_saveraw(void) { - uint32_t address = parse_unsigned(0,16777216,16); - uint32_t length = parse_unsigned(0,16777216,16); - if(address != -1 && length != -1) - save_sram((uint8_t*)curchar, length, address); -} +static void cmd_saveraw( void ) +{ + uint32_t address = parse_unsigned( 0, 16777216, 16 ); + uint32_t length = parse_unsigned( 0, 16777216, 16 ); -static void cmd_d4(void) { - int32_t hz; - - if(get_cic_state() != CIC_PAIR) { - printf("not in pair mode\n"); - } else { - hz = parse_unsigned(50,60,10); - if(hz==50) { - cic_d4(CIC_PAL); - } else { - cic_d4(CIC_NTSC); + if ( address != -1 && length != -1 ) + { + save_sram( ( uint8_t * )curchar, length, address ); } - printf("ok\n"); - } } -static void cmd_vmode(void) { - int32_t hz; - if(get_cic_state() != CIC_PAIR) { - printf("not in pair mode\n"); - } else { - hz = parse_unsigned(50,60,10); - if(hz==50) { - cic_videomode(CIC_PAL); - } else { - cic_videomode(CIC_NTSC); +static void cmd_d4( void ) +{ + int32_t hz; + + if ( get_cic_state() != CIC_PAIR ) + { + printf( "not in pair mode\n" ); } - printf("ok\n"); - } -} + else + { + hz = parse_unsigned( 50, 60, 10 ); -void cmd_put(void) { - if(*curchar != 0) { - file_open((uint8_t*)curchar, FA_CREATE_ALWAYS | FA_WRITE); - if(file_res) { - printf("FAIL: error opening file %s\n", curchar); - } else { - printf("OK, start xmodem transfer now.\n"); - xmodem_rxfile(&file_handle); + if ( hz == 50 ) + { + cic_d4( CIC_PAL ); + } + else + { + cic_d4( CIC_NTSC ); + } + + printf( "ok\n" ); } - file_close(); - } else { - printf("Usage: put \n"); - } } -void cmd_rm(void) { - FRESULT res = f_unlink(curchar); - if(res) printf("Error %d removing %s\n", res, curchar); +static void cmd_vmode( void ) +{ + int32_t hz; + + if ( get_cic_state() != CIC_PAIR ) + { + printf( "not in pair mode\n" ); + } + else + { + hz = parse_unsigned( 50, 60, 10 ); + + if ( hz == 50 ) + { + cic_videomode( CIC_PAL ); + } + else + { + cic_videomode( CIC_NTSC ); + } + + printf( "ok\n" ); + } } -void cmd_mkdir(void) { - FRESULT res = f_mkdir(curchar); - if(res) printf("Error %d creating directory %s\n", res, curchar); +void cmd_put( void ) +{ + if ( *curchar != 0 ) + { + file_open( ( uint8_t * )curchar, FA_CREATE_ALWAYS | FA_WRITE ); + + if ( file_res ) + { + printf( "FAIL: error opening file %s\n", curchar ); + } + else + { + printf( "OK, start xmodem transfer now.\n" ); + xmodem_rxfile( &file_handle ); + } + + file_close(); + } + else + { + printf( "Usage: put \n" ); + } } -void cmd_mapper(void) { - int32_t mapper; - mapper = parse_unsigned(0,7,10); - set_mapper((uint8_t)mapper & 0x7); - printf("mapper set to %ld\n", mapper); +void cmd_rm( void ) +{ + FRESULT res = f_unlink( curchar ); + + if ( res ) + { + printf( "Error %d removing %s\n", res, curchar ); + } } -void cmd_sreset(void) { - if(*curchar != 0) { - int32_t resetstate; - resetstate = parse_unsigned(0,1,10); - snes_reset(resetstate); - } else { - snes_reset_pulse(); - } -} -void cmd_settime(void) { - struct tm time; - if(strlen(curchar) != 4+2+2 + 2+2+2) { - printf("invalid time format (need YYYYMMDDhhmmss)\n"); - } else { - time.tm_sec = atoi(curchar+4+2+2+2+2); - curchar[4+2+2+2+2] = 0; - time.tm_min = atoi(curchar+4+2+2+2); - curchar[4+2+2+2] = 0; - time.tm_hour = atoi(curchar+4+2+2); - curchar[4+2+2] = 0; - time.tm_mday = atoi(curchar+4+2); - curchar[4+2] = 0; - time.tm_mon = atoi(curchar+4); - curchar[4] = 0; - time.tm_year = atoi(curchar); - set_rtc(&time); - } +void cmd_mkdir( void ) +{ + FRESULT res = f_mkdir( curchar ); + + if ( res ) + { + printf( "Error %d creating directory %s\n", res, curchar ); + } } -void cmd_time(void) { - struct tm time; - read_rtc(&time); - printf("%04d-%02d-%02d %02d:%02d:%02d\n", time.tm_year, time.tm_mon, - time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec); +void cmd_mapper( void ) +{ + int32_t mapper; + mapper = parse_unsigned( 0, 7, 10 ); + set_mapper( ( uint8_t )mapper & 0x7 ); + printf( "mapper set to %ld\n", mapper ); } -void cmd_setfeature(void) { - uint8_t feat = parse_unsigned(0, 255, 16); - fpga_set_features(feat); +void cmd_sreset( void ) +{ + if ( *curchar != 0 ) + { + int32_t resetstate; + resetstate = parse_unsigned( 0, 1, 10 ); + snes_reset( resetstate ); + } + else + { + snes_reset_pulse(); + } +} +void cmd_settime( void ) +{ + struct tm time; + + if ( strlen( curchar ) != 4 + 2 + 2 + 2 + 2 + 2 ) + { + printf( "invalid time format (need YYYYMMDDhhmmss)\n" ); + } + else + { + time.tm_sec = atoi( curchar + 4 + 2 + 2 + 2 + 2 ); + curchar[4 + 2 + 2 + 2 + 2] = 0; + time.tm_min = atoi( curchar + 4 + 2 + 2 + 2 ); + curchar[4 + 2 + 2 + 2] = 0; + time.tm_hour = atoi( curchar + 4 + 2 + 2 ); + curchar[4 + 2 + 2] = 0; + time.tm_mday = atoi( curchar + 4 + 2 ); + curchar[4 + 2] = 0; + time.tm_mon = atoi( curchar + 4 ); + curchar[4] = 0; + time.tm_year = atoi( curchar ); + set_rtc( &time ); + } } -void cmd_hexdump(void) { - uint32_t offset = parse_unsigned(0, 16777215, 16); - uint32_t len = parse_unsigned(0, 16777216, 16); - sram_hexdump(offset, len); +void cmd_time( void ) +{ + struct tm time; + read_rtc( &time ); + printf( "%04d-%02d-%02d %02d:%02d:%02d\n", time.tm_year, time.tm_mon, + time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec ); } -void cmd_w8(void) { - uint32_t offset = parse_unsigned(0, 16777215, 16); - uint8_t val = parse_unsigned(0, 255, 16); - sram_writebyte(val, offset); +void cmd_setfeature( void ) +{ + uint8_t feat = parse_unsigned( 0, 255, 16 ); + fpga_set_features( feat ); } -void cmd_w16(void) { - uint32_t offset = parse_unsigned(0, 16777215, 16); - uint16_t val = parse_unsigned(0, 65535, 16); - sram_writeshort(val, offset); +void cmd_hexdump( void ) +{ + uint32_t offset = parse_unsigned( 0, 16777215, 16 ); + uint32_t len = parse_unsigned( 0, 16777216, 16 ); + sram_hexdump( offset, len ); } -void cmd_memset(void) { - uint32_t offset = parse_unsigned(0, 16777215, 16); - uint32_t len = parse_unsigned(0, 16777216, 16); - uint8_t val = parse_unsigned(0, 255, 16); - sram_memset(offset, len, val); +void cmd_w8( void ) +{ + uint32_t offset = parse_unsigned( 0, 16777215, 16 ); + uint8_t val = parse_unsigned( 0, 255, 16 ); + sram_writebyte( val, offset ); +} + +void cmd_w16( void ) +{ + uint32_t offset = parse_unsigned( 0, 16777215, 16 ); + uint16_t val = parse_unsigned( 0, 65535, 16 ); + sram_writeshort( val, offset ); +} + +void cmd_memset( void ) +{ + uint32_t offset = parse_unsigned( 0, 16777215, 16 ); + uint32_t len = parse_unsigned( 0, 16777216, 16 ); + uint8_t val = parse_unsigned( 0, 255, 16 ); + sram_memset( offset, len, val ); } /* ------------------------------------------------------------------------- */ /* CLI interface functions */ /* ------------------------------------------------------------------------- */ -void cli_init(void) { +void cli_init( void ) +{ } -void cli_entrycheck() { - if(uart_gotc() && uart_getc() == 27) { - printf("*** BREAK\n"); - cli_loop(); - } -} - -void cli_loop(void) { - while (1) { - curchar = getline(">"); - printf("\n"); - - /* Process medium changes before executing the command */ - if (disk_state != DISK_OK && disk_state != DISK_REMOVED) { - FRESULT res; - - printf("Medium changed... "); - res = f_mount(0,&fatfs); - if (res != FR_OK) { - printf("Failed to mount new medium, result %d\n",res); - } else { - printf("Ok\n"); - } - +void cli_entrycheck() +{ + if ( uart_gotc() && uart_getc() == 27 ) + { + printf( "*** BREAK\n" ); + cli_loop(); } +} - /* Remove whitespace */ - while (*curchar == ' ') curchar++; - while (strlen(curchar) > 0 && curchar[strlen(curchar)-1] == ' ') - curchar[strlen(curchar)-1] = 0; +void cli_loop( void ) +{ + while ( 1 ) + { + curchar = getline( ">" ); + printf( "\n" ); - /* Ignore empty lines */ - if (strlen(curchar) == 0) - continue; + /* Process medium changes before executing the command */ + if ( disk_state != DISK_OK && disk_state != DISK_REMOVED ) + { + FRESULT res; - /* Parse command */ - int8_t command = parse_wordlist(command_words); - if (command < 0) - continue; + printf( "Medium changed... " ); + res = f_mount( 0, &fatfs ); + + if ( res != FR_OK ) + { + printf( "Failed to mount new medium, result %d\n", res ); + } + else + { + printf( "Ok\n" ); + } + + } + + /* Remove whitespace */ + while ( *curchar == ' ' ) + { + curchar++; + } + + while ( strlen( curchar ) > 0 && curchar[strlen( curchar ) - 1] == ' ' ) + { + curchar[strlen( curchar ) - 1] = 0; + } + + /* Ignore empty lines */ + if ( strlen( curchar ) == 0 ) + { + continue; + } + + /* Parse command */ + int8_t command = parse_wordlist( command_words ); + + if ( command < 0 ) + { + continue; + } - FRESULT res; - switch (command) { - case CMD_CD: + FRESULT res; + + switch ( command ) + { + case CMD_CD: #if _FS_RPATH - if (strlen(curchar) == 0) { - f_getcwd((TCHAR*)file_lfn, 255); - printf("%s\n",file_lfn); - break; - } + if ( strlen( curchar ) == 0 ) + { + f_getcwd( ( TCHAR * )file_lfn, 255 ); + printf( "%s\n", file_lfn ); + break; + } + + res = f_chdir( ( const TCHAR * )curchar ); + + if ( res != FR_OK ) + { + printf( "chdir %s failed with result %d\n", curchar, res ); + } + else + { + printf( "Ok.\n" ); + } - res = f_chdir((const TCHAR *)curchar); - if (res != FR_OK) { - printf("chdir %s failed with result %d\n",curchar,res); - } else { - printf("Ok.\n"); - } #else - printf("cd not supported.\n"); - res; + printf( "cd not supported.\n" ); + res; #endif - break; - case CMD_RESET: - cmd_reset(); - break; + break; - case CMD_SRESET: - cmd_sreset(); - break; + case CMD_RESET: + cmd_reset(); + break; - case CMD_DIR: - case CMD_LS: - cmd_show_directory(); - break; + case CMD_SRESET: + cmd_sreset(); + break; - case CMD_EXIT: - return; - break; + case CMD_DIR: + case CMD_LS: + cmd_show_directory(); + break; - case CMD_LOADROM: - cmd_loadrom(); - break; + case CMD_EXIT: + return; + break; - case CMD_LOADRAW: - cmd_loadraw(); - break; + case CMD_LOADROM: + cmd_loadrom(); + break; - case CMD_SAVERAW: - cmd_saveraw(); - break; + case CMD_LOADRAW: + cmd_loadraw(); + break; - case CMD_RM: - cmd_rm(); - break; + case CMD_SAVERAW: + cmd_saveraw(); + break; - case CMD_MKDIR: - cmd_mkdir(); - break; + case CMD_RM: + cmd_rm(); + break; - case CMD_D4: - cmd_d4(); - break; + case CMD_MKDIR: + cmd_mkdir(); + break; - case CMD_VMODE: - cmd_vmode(); - break; + case CMD_D4: + cmd_d4(); + break; - case CMD_PUT: - cmd_put(); - break; + case CMD_VMODE: + cmd_vmode(); + break; - case CMD_MAPPER: - cmd_mapper(); - break; + case CMD_PUT: + cmd_put(); + break; - case CMD_SETTIME: - cmd_settime(); - break; + case CMD_MAPPER: + cmd_mapper(); + break; - case CMD_TIME: - cmd_time(); - break; + case CMD_SETTIME: + cmd_settime(); + break; - case CMD_TEST: - testbattery(); - break; + case CMD_TIME: + cmd_time(); + break; - case CMD_SETFEATURE: - cmd_setfeature(); - break; + case CMD_TEST: + testbattery(); + break; - case CMD_HEXDUMP: - cmd_hexdump(); - break; + case CMD_SETFEATURE: + cmd_setfeature(); + break; - case CMD_W8: - cmd_w8(); - break; + case CMD_HEXDUMP: + cmd_hexdump(); + break; - case CMD_W16: - cmd_w16(); - break; + case CMD_W8: + cmd_w8(); + break; - case CMD_MEMSET: - cmd_memset(); - break; + case CMD_W16: + cmd_w16(); + break; + case CMD_MEMSET: + cmd_memset(); + break; + + case CMD_MEMTEST: + test_mem(); + break; + + } } - } } diff --git a/src/cli.h b/src/cli.h index 69c2276..262c440 100644 --- a/src/cli.h +++ b/src/cli.h @@ -27,8 +27,8 @@ #ifndef CLI_H #define CLI_H -void cli_init(void); -void cli_loop(void); -void cli_entrycheck(void); +void cli_init( void ); +void cli_loop( void ); +void cli_entrycheck( void ); #endif diff --git a/src/clock.c b/src/clock.c index 7cd5c8d..34dff50 100644 --- a/src/clock.c +++ b/src/clock.c @@ -7,101 +7,116 @@ #include "bits.h" #include "uart.h" -void clock_disconnect() { - disconnectPLL0(); - disablePLL0(); +void clock_disconnect() +{ + disconnectPLL0(); + disablePLL0(); } -void clock_init() { +void clock_init() +{ -/* set flash access time to 5 clks (80 DAC freq = 44099.5 Hz - -> FPGA freq = 11289473.7Hz - First, disable and disconnect PLL0. -*/ - clock_disconnect(); + /* setup PLL0 for ~44100*256*8 Hz + Base clock: 12MHz + Multiplier: 429 + Pre-Divisor: 19 + Divisor: 6 + (want: 90316800, get: 90315789.47) + -> DAC freq = 44099.5 Hz + -> FPGA freq = 11289473.7Hz + First, disable and disconnect PLL0. + */ + clock_disconnect(); -/* PLL is disabled and disconnected. setup PCLK NOW as it cannot be changed - reliably with PLL0 connected. - see: - http://ics.nxp.com/support/documents/microcontrollers/pdf/errata.lpc1754.pdf -*/ + /* PLL is disabled and disconnected. setup PCLK NOW as it cannot be changed + reliably with PLL0 connected. + see: + http://ics.nxp.com/support/documents/microcontrollers/pdf/errata.lpc1754.pdf + */ -/* continue with PLL0 setup: - enable the xtal oscillator and wait for it to become stable - set the oscillator as clk source for PLL0 - set PLL0 multiplier+predivider - enable PLL0 - set CCLK divider - wait for PLL0 to lock - connect PLL0 - done - */ - enableMainOsc(); - setClkSrc(CLKSRC_MAINOSC); - setPLL0MultPrediv(22, 1); - enablePLL0(); - setCCLKDiv(6); - connectPLL0(); + /* continue with PLL0 setup: + enable the xtal oscillator and wait for it to become stable + set the oscillator as clk source for PLL0 + set PLL0 multiplier+predivider + enable PLL0 + set CCLK divider + wait for PLL0 to lock + connect PLL0 + done + */ + enableMainOsc(); + setClkSrc( CLKSRC_MAINOSC ); + setPLL0MultPrediv( 22, 1 ); + enablePLL0(); + setCCLKDiv( 6 ); + connectPLL0(); } -void setFlashAccessTime(uint8_t clocks) { - LPC_SC->FLASHCFG=FLASHTIM(clocks); +void setFlashAccessTime( uint8_t clocks ) +{ + LPC_SC->FLASHCFG = FLASHTIM( clocks ); } -void setPLL0MultPrediv(uint16_t mult, uint8_t prediv) { - LPC_SC->PLL0CFG=PLL_MULT(mult) | PLL_PREDIV(prediv); - PLL0feed(); +void setPLL0MultPrediv( uint16_t mult, uint8_t prediv ) +{ + LPC_SC->PLL0CFG = PLL_MULT( mult ) | PLL_PREDIV( prediv ); + PLL0feed(); } -void enablePLL0() { - LPC_SC->PLL0CON |= PLLE0; - PLL0feed(); +void enablePLL0() +{ + LPC_SC->PLL0CON |= PLLE0; + PLL0feed(); } -void disablePLL0() { - LPC_SC->PLL0CON &= ~PLLE0; - PLL0feed(); +void disablePLL0() +{ + LPC_SC->PLL0CON &= ~PLLE0; + PLL0feed(); } -void connectPLL0() { - while(!(LPC_SC->PLL0STAT & PLOCK0)); - LPC_SC->PLL0CON |= PLLC0; - PLL0feed(); +void connectPLL0() +{ + while ( !( LPC_SC->PLL0STAT & PLOCK0 ) ); + + LPC_SC->PLL0CON |= PLLC0; + PLL0feed(); } -void disconnectPLL0() { - LPC_SC->PLL0CON &= ~PLLC0; - PLL0feed(); +void disconnectPLL0() +{ + LPC_SC->PLL0CON &= ~PLLC0; + PLL0feed(); } -void setCCLKDiv(uint8_t div) { - LPC_SC->CCLKCFG=CCLK_DIV(div); +void setCCLKDiv( uint8_t div ) +{ + LPC_SC->CCLKCFG = CCLK_DIV( div ); } -void enableMainOsc() { - LPC_SC->SCS=OSCEN; - while(!(LPC_SC->SCS&OSCSTAT)); +void enableMainOsc() +{ + LPC_SC->SCS = OSCEN; + + while ( !( LPC_SC->SCS & OSCSTAT ) ); } -void disableMainOsc() { - LPC_SC->SCS=0; +void disableMainOsc() +{ + LPC_SC->SCS = 0; } -void PLL0feed() { - LPC_SC->PLL0FEED=0xaa; - LPC_SC->PLL0FEED=0x55; +void PLL0feed() +{ + LPC_SC->PLL0FEED = 0xaa; + LPC_SC->PLL0FEED = 0x55; } -void setClkSrc(uint8_t src) { - LPC_SC->CLKSRCSEL=src; +void setClkSrc( uint8_t src ) +{ + LPC_SC->CLKSRCSEL = src; } diff --git a/src/clock.h b/src/clock.h index 503d1d0..874fb1c 100644 --- a/src/clock.h +++ b/src/clock.h @@ -18,60 +18,60 @@ #define PCLK_CCLK2(x) (2<<(x)) /* shift values for use with PCLKSEL0 */ -#define PCLK_WDT (0) -#define PCLK_TIMER0 (2) -#define PCLK_TIMER1 (4) -#define PCLK_UART0 (6) -#define PCLK_UART1 (8) -#define PCLK_PWM1 (12) -#define PCLK_I2C0 (14) -#define PCLK_SPI (16) -#define PCLK_SSP1 (20) -#define PCLK_DAC (22) -#define PCLK_ADC (24) -#define PCLK_CAN1 (26) -#define PCLK_CAN2 (28) -#define PCLK_ACF (30) +#define PCLK_WDT (0) +#define PCLK_TIMER0 (2) +#define PCLK_TIMER1 (4) +#define PCLK_UART0 (6) +#define PCLK_UART1 (8) +#define PCLK_PWM1 (12) +#define PCLK_I2C0 (14) +#define PCLK_SPI (16) +#define PCLK_SSP1 (20) +#define PCLK_DAC (22) +#define PCLK_ADC (24) +#define PCLK_CAN1 (26) +#define PCLK_CAN2 (28) +#define PCLK_ACF (30) /* shift values for use with PCLKSEL1 */ -#define PCLK_QEI (0) -#define PCLK_GPIOINT (2) -#define PCLK_PCB (4) -#define PCLK_I2C1 (6) -#define PCLK_SSP0 (10) -#define PCLK_TIMER2 (12) +#define PCLK_QEI (0) +#define PCLK_GPIOINT (2) +#define PCLK_PCB (4) +#define PCLK_I2C1 (6) +#define PCLK_SSP0 (10) +#define PCLK_TIMER2 (12) #define PCLK_TIMER3 (14) -#define PCLK_UART2 (16) -#define PCLK_UART3 (18) -#define PCLK_I2C2 (20) -#define PCLK_I2S (22) -#define PCLK_RIT (26) -#define PCLK_SYSCON (28) -#define PCLK_MC (30) +#define PCLK_UART2 (16) +#define PCLK_UART3 (18) +#define PCLK_I2C2 (20) +#define PCLK_I2S (22) +#define PCLK_RIT (26) +#define PCLK_SYSCON (28) +#define PCLK_MC (30) -void clock_disconnect(void); +void clock_disconnect( void ); -void clock_init(void); +void clock_init( void ); -void setFlashAccessTime(uint8_t clocks); +void setFlashAccessTime( uint8_t clocks ); -void setPLL0MultPrediv(uint16_t mult, uint8_t prediv); +void setPLL0MultPrediv( uint16_t mult, uint8_t prediv ); -void enablePLL0(void); +void enablePLL0( void ); -void disablePLL0(void); +void disablePLL0( void ); -void connectPLL0(void); +void connectPLL0( void ); -void disconnectPLL0(void); +void disconnectPLL0( void ); -void setCCLKDiv(uint8_t div); +void setCCLKDiv( uint8_t div ); -void enableMainOsc(void); +void enableMainOsc( void ); -void disableMainOsc(void); +void disableMainOsc( void ); -void PLL0feed(void); +void PLL0feed( void ); -void setClkSrc(uint8_t src); +void setClkSrc( uint8_t src ); #endif diff --git a/src/config.h b/src/config.h index adb6b5d..95e35d5 100644 --- a/src/config.h +++ b/src/config.h @@ -11,9 +11,9 @@ #define IN_AHBRAM __attribute__ ((section(".ahbram"))) #define SD_DT_INT_SETUP() do {\ - BITBAND(LPC_GPIOINT->IO2IntEnR, SD_DT_BIT) = 1;\ - BITBAND(LPC_GPIOINT->IO2IntEnF, SD_DT_BIT) = 1;\ - } while(0) + BITBAND(LPC_GPIOINT->IO2IntEnR, SD_DT_BIT) = 1;\ + BITBAND(LPC_GPIOINT->IO2IntEnF, SD_DT_BIT) = 1;\ + } while(0) #define SD_CHANGE_DETECT (BITBAND(LPC_GPIOINT->IO2IntStatR, SD_DT_BIT)\ |BITBAND(LPC_GPIOINT->IO2IntStatF, SD_DT_BIT)) @@ -33,7 +33,7 @@ // #define SD_CHANGE_VECT // #define CONFIG_SD_DATACRC 1 -#define CONFIG_UART_NUM 3 +#define CONFIG_UART_NUM 3 // #define CONFIG_CPU_FREQUENCY 90315789 #define CONFIG_CPU_FREQUENCY 88000000 //#define CONFIG_CPU_FREQUENCY 46000000 @@ -65,7 +65,7 @@ #define QSORT_MAXELEM 2048 #define SORT_STRLEN 256 -#define CLTBL_SIZE 100 +#define CLTBL_SIZE 100 #define DIR_FILE_MAX 16380 diff --git a/src/crc.h b/src/crc.h index 34e0053..093c327 100644 --- a/src/crc.h +++ b/src/crc.h @@ -1,9 +1,9 @@ #ifndef CRC_H #define CRC_H -uint8_t crc7update(uint8_t crc, uint8_t data); -uint16_t crc_xmodem_update(uint16_t crc, uint8_t data); -uint16_t crc_xmodem_block(uint16_t crc, const uint8_t *data, uint32_t length); +uint8_t crc7update( uint8_t crc, uint8_t data ); +uint16_t crc_xmodem_update( uint16_t crc, uint8_t data ); +uint16_t crc_xmodem_block( uint16_t crc, const uint8_t *data, uint32_t length ); // AVR-libc compatibility #define _crc_xmodem_update(crc,data) crc_xmodem_update(crc,data) diff --git a/src/crc16.c b/src/crc16.c index 4dd98ac..f0c9df0 100644 --- a/src/crc16.c +++ b/src/crc16.c @@ -20,7 +20,8 @@ /** * Static table used for the table_driven implementation. *****************************************************************************/ -static const uint16_t crc_table[256] = { +static const uint16_t crc_table[256] = +{ 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, @@ -63,12 +64,12 @@ static const uint16_t crc_table[256] = { * \param data_len Number of bytes in the \a data buffer. * \return The updated crc value. *****************************************************************************/ -uint16_t crc16_update(uint16_t crc, const unsigned char data) +uint16_t crc16_update( uint16_t crc, const unsigned char data ) { - unsigned int tbl_idx; - tbl_idx = (crc ^ data) & 0xff; - crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffff; - return crc & 0xffff; + unsigned int tbl_idx; + tbl_idx = ( crc ^ data ) & 0xff; + crc = ( crc_table[tbl_idx] ^ ( crc >> 8 ) ) & 0xffff; + return crc & 0xffff; } diff --git a/src/crc16.h b/src/crc16.h index e13ec45..53077f4 100644 --- a/src/crc16.h +++ b/src/crc16.h @@ -37,7 +37,7 @@ extern "C" { * \param data_len Number of bytes in the \a data buffer. * \return The updated crc value. *****************************************************************************/ -uint16_t crc16_update(uint16_t crc, const unsigned char data); +uint16_t crc16_update( uint16_t crc, const unsigned char data ); #ifdef __cplusplus } /* closing brace for extern "C" */ diff --git a/src/crc32.c b/src/crc32.c index 7928cf2..7cfe973 100644 --- a/src/crc32.c +++ b/src/crc32.c @@ -22,71 +22,72 @@ /** * Static table used for the table_driven implementation. *****************************************************************************/ -static const uint32_t crc32_table[256] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, - 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, - 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, - 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, - 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, - 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, - 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, - 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, - 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, - 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, - 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, - 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, - 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, - 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, - 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, - 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, - 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, - 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, - 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, - 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, - 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, - 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, - 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, - 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, - 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, - 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, - 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, - 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, - 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, - 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, - 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, - 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, - 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, - 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, - 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, - 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, - 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, - 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +static const uint32_t crc32_table[256] = +{ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; /** @@ -97,14 +98,14 @@ static const uint32_t crc32_table[256] = { * \param data_len Number of bytes in the \a data buffer. * \return The updated crc value. *****************************************************************************/ -uint32_t crc32_update(uint32_t crc, const unsigned char data) +uint32_t crc32_update( uint32_t crc, const unsigned char data ) { - unsigned int tbl_idx; + unsigned int tbl_idx; - tbl_idx = (crc ^ data) & 0xff; - crc = (crc32_table[tbl_idx] ^ (crc >> 8)) & 0xffffffff; + tbl_idx = ( crc ^ data ) & 0xff; + crc = ( crc32_table[tbl_idx] ^ ( crc >> 8 ) ) & 0xffffffff; - return crc & 0xffffffff; + return crc & 0xffffffff; } diff --git a/src/crc32.h b/src/crc32.h index 9da3054..af090b2 100644 --- a/src/crc32.h +++ b/src/crc32.h @@ -34,9 +34,9 @@ extern "C" { * * \return The initial crc value. *****************************************************************************/ -static inline uint32_t crc_init(void) +static inline uint32_t crc_init( void ) { - return 0xffffffff; + return 0xffffffff; } /** @@ -47,7 +47,7 @@ static inline uint32_t crc_init(void) * \param data_len Number of bytes in the \a data buffer. * \return The updated crc value. *****************************************************************************/ -uint32_t crc32_update(uint32_t crc, const unsigned char data); +uint32_t crc32_update( uint32_t crc, const unsigned char data ); /** * Calculate the final crc value. @@ -55,9 +55,9 @@ uint32_t crc32_update(uint32_t crc, const unsigned char data); * \param crc The current crc value. * \return The final crc value. *****************************************************************************/ -static inline uint32_t crc32_finalize(uint32_t crc) +static inline uint32_t crc32_finalize( uint32_t crc ) { - return crc ^ 0xffffffff; + return crc ^ 0xffffffff; } diff --git a/src/diskio.h b/src/diskio.h index 05787ad..c3c4287 100644 --- a/src/diskio.h +++ b/src/diskio.h @@ -4,8 +4,8 @@ #ifndef _DISKIO -#define _READONLY 0 /* 1: Remove write functions */ -#define _USE_IOCTL 1 /* 1: Use disk_ioctl fucntion */ +#define _READONLY 0 /* 1: Remove write functions */ +#define _USE_IOCTL 1 /* 1: Use disk_ioctl fucntion */ #include @@ -13,15 +13,16 @@ /* Status of Disk Functions */ -typedef BYTE DSTATUS; +typedef BYTE DSTATUS; /* Results of Disk Functions */ -typedef enum { - RES_OK = 0, /* 0: Successful */ - RES_ERROR, /* 1: R/W Error */ - RES_WRPRT, /* 2: Write Protected */ - RES_NOTRDY, /* 3: Not Ready */ - RES_PARERR /* 4: Invalid Parameter */ +typedef enum +{ + RES_OK = 0, /* 0: Successful */ + RES_ERROR, /* 1: R/W Error */ + RES_WRPRT, /* 2: Write Protected */ + RES_NOTRDY, /* 3: Not Ready */ + RES_PARERR /* 4: Invalid Parameter */ } DRESULT; /** @@ -35,12 +36,13 @@ typedef enum { * This is the struct returned in the data buffer when disk_getinfo * is called with page=0. */ -typedef struct { - uint8_t validbytes; - uint8_t maxpage; - uint8_t disktype; - uint8_t sectorsize; /* divided by 256 */ - uint32_t sectorcount; /* 2 TB should be enough... (512 byte sectors) */ +typedef struct +{ + uint8_t validbytes; + uint8_t maxpage; + uint8_t disktype; + uint8_t sectorsize; /* divided by 256 */ + uint32_t sectorcount; /* 2 TB should be enough... (512 byte sectors) */ } diskinfo0_t; @@ -48,16 +50,16 @@ typedef struct { /*---------------------------------------*/ /* Prototypes for disk control functions */ -int assign_drives (int, int); -DSTATUS disk_initialize (BYTE); -DSTATUS disk_status (BYTE); -DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE); -#if _READONLY == 0 -DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE); +int assign_drives ( int, int ); +DSTATUS disk_initialize ( BYTE ); +DSTATUS disk_status ( BYTE ); +DRESULT disk_read ( BYTE, BYTE *, DWORD, BYTE ); +#if _READONLY == 0 +DRESULT disk_write ( BYTE, const BYTE *, DWORD, BYTE ); #endif -DRESULT disk_ioctl (BYTE, BYTE, void*); +DRESULT disk_ioctl ( BYTE, BYTE, void * ); -void disk_init(void); +void disk_init( void ); /* Will be set to DISK_ERROR if any access on the card fails */ enum diskstates { DISK_CHANGED = 0, DISK_REMOVED, DISK_OK, DISK_ERROR }; @@ -79,39 +81,39 @@ extern volatile enum diskstates disk_state; /* Disk Status Bits (DSTATUS) */ -#define STA_NOINIT 0x01 /* Drive not initialized */ -#define STA_NODISK 0x02 /* No medium in the drive */ -#define STA_PROTECT 0x04 /* Write protected */ +#define STA_NOINIT 0x01 /* Drive not initialized */ +#define STA_NODISK 0x02 /* No medium in the drive */ +#define STA_PROTECT 0x04 /* Write protected */ /* Command code for disk_ioctrl fucntion */ /* Generic command (defined for FatFs) */ -#define CTRL_SYNC 0 /* Flush disk cache (for write functions) */ -#define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */ -#define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */ -#define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */ -#define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */ +#define CTRL_SYNC 0 /* Flush disk cache (for write functions) */ +#define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */ +#define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */ +#define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */ +#define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */ /* Generic command */ -#define CTRL_POWER 5 /* Get/Set power status */ -#define CTRL_LOCK 6 /* Lock/Unlock media removal */ -#define CTRL_EJECT 7 /* Eject media */ +#define CTRL_POWER 5 /* Get/Set power status */ +#define CTRL_LOCK 6 /* Lock/Unlock media removal */ +#define CTRL_EJECT 7 /* Eject media */ /* MMC/SDC specific ioctl command */ -#define MMC_GET_TYPE 10 /* Get card type */ -#define MMC_GET_CSD 11 /* Get CSD */ -#define MMC_GET_CID 12 /* Get CID */ -#define MMC_GET_OCR 13 /* Get OCR */ -#define MMC_GET_SDSTAT 14 /* Get SD status */ +#define MMC_GET_TYPE 10 /* Get card type */ +#define MMC_GET_CSD 11 /* Get CSD */ +#define MMC_GET_CID 12 /* Get CID */ +#define MMC_GET_OCR 13 /* Get OCR */ +#define MMC_GET_SDSTAT 14 /* Get SD status */ /* ATA/CF specific ioctl command */ -#define ATA_GET_REV 20 /* Get F/W revision */ -#define ATA_GET_MODEL 21 /* Get model name */ -#define ATA_GET_SN 22 /* Get serial number */ +#define ATA_GET_REV 20 /* Get F/W revision */ +#define ATA_GET_MODEL 21 /* Get model name */ +#define ATA_GET_SN 22 /* Get serial number */ /* NAND specific ioctl command */ -#define NAND_FORMAT 30 /* Create physical format */ +#define NAND_FORMAT 30 /* Create physical format */ #define _DISKIO diff --git a/src/faulthandler.c b/src/faulthandler.c index 47d595f..b2536ee 100644 --- a/src/faulthandler.c +++ b/src/faulthandler.c @@ -1,20 +1,25 @@ #include #include "uart.h" -void HardFault_Handler(void) { - printf("HFSR: %lx\n", SCB->HFSR); - while (1) ; +void HardFault_Handler( void ) +{ + printf( "HFSR: %lx\n", SCB->HFSR ); + + while ( 1 ) ; } -void MemManage_Handler(void) { - printf("MemManage - CFSR: %lx; MMFAR: %lx\n", SCB->CFSR, SCB->MMFAR); +void MemManage_Handler( void ) +{ + printf( "MemManage - CFSR: %lx; MMFAR: %lx\n", SCB->CFSR, SCB->MMFAR ); } -void BusFault_Handler(void) { - printf("BusFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR); +void BusFault_Handler( void ) +{ + printf( "BusFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR ); } -void UsageFault_Handler(void) { - printf("UsageFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR); +void UsageFault_Handler( void ) +{ + printf( "UsageFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR ); } diff --git a/src/ff.c b/src/ff.c index 62affd1..8c09eca 100644 --- a/src/ff.c +++ b/src/ff.c @@ -85,8 +85,8 @@ / Fixed f_mkfs() creates wrong FAT32 volume. /---------------------------------------------------------------------------*/ -#include "ff.h" /* FatFs configurations and declarations */ -#include "diskio.h" /* Declarations of low level disk I/O functions */ +#include "ff.h" /* FatFs configurations and declarations */ +#include "diskio.h" /* Declarations of low level disk I/O functions */ #include "config.h" #include "uart.h" @@ -106,9 +106,9 @@ #error Wrong sector size. #endif #if _MAX_SS != 512 -#define SS(fs) ((fs)->ssize) /* Multiple sector size */ +#define SS(fs) ((fs)->ssize) /* Multiple sector size */ #else -#define SS(fs) 512U /* Fixed sector size */ +#define SS(fs) 512U /* Fixed sector size */ #endif @@ -117,14 +117,14 @@ #if _USE_LFN == 1 #error Static LFN work area must not be used in re-entrant configuration. #endif -#define ENTER_FF(fs) { if (!lock_fs(fs)) return FR_TIMEOUT; } -#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } +#define ENTER_FF(fs) { if (!lock_fs(fs)) return FR_TIMEOUT; } +#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } #else -#define ENTER_FF(fs) -#define LEAVE_FF(fs, res) return res +#define ENTER_FF(fs) +#define LEAVE_FF(fs, res) return res #endif -#define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); } +#define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); } /* File shareing feature */ @@ -132,119 +132,120 @@ #if _FS_READONLY #error _FS_SHARE must be 0 on read-only cfg. #endif -typedef struct { - FATFS *fs; /* File ID 1, volume (NULL:blank entry) */ - DWORD clu; /* File ID 2, directory */ - WORD idx; /* File ID 3, directory index */ - WORD ctr; /* File open counter, 0:none, 0x01..0xFF:read open count, 0x100:write mode */ +typedef struct +{ + FATFS *fs; /* File ID 1, volume (NULL:blank entry) */ + DWORD clu; /* File ID 2, directory */ + WORD idx; /* File ID 3, directory index */ + WORD ctr; /* File open counter, 0:none, 0x01..0xFF:read open count, 0x100:write mode */ } FILESEM; #endif /* Misc definitions */ -#define LD_CLUST(dir) (((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO)) +#define LD_CLUST(dir) (((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO)) #define ST_CLUST(dir,cl) {ST_WORD(dir+DIR_FstClusLO, cl); ST_WORD(dir+DIR_FstClusHI, (DWORD)cl>>16);} /* Character code support macros */ -#define IsUpper(c) (((c)>='A')&&((c)<='Z')) -#define IsLower(c) (((c)>='a')&&((c)<='z')) -#define IsDigit(c) (((c)>='0')&&((c)<='9')) +#define IsUpper(c) (((c)>='A')&&((c)<='Z')) +#define IsLower(c) (((c)>='a')&&((c)<='z')) +#define IsDigit(c) (((c)>='0')&&((c)<='9')) -#if _DF1S /* Code page is DBCS */ +#if _DF1S /* Code page is DBCS */ -#ifdef _DF2S /* Two 1st byte areas */ -#define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E)) -#else /* One 1st byte area */ -#define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) +#ifdef _DF2S /* Two 1st byte areas */ +#define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E)) +#else /* One 1st byte area */ +#define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) #endif -#ifdef _DS3S /* Three 2nd byte areas */ -#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E)) -#else /* Two 2nd byte areas */ -#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E)) +#ifdef _DS3S /* Three 2nd byte areas */ +#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E)) +#else /* Two 2nd byte areas */ +#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E)) #endif -#else /* Code page is SBCS */ +#else /* Code page is SBCS */ -#define IsDBCS1(c) 0 -#define IsDBCS2(c) 0 +#define IsDBCS1(c) 0 +#define IsDBCS2(c) 0 #endif /* _DF1S */ /* Name status flags */ -#define NS 11 /* Offset of name status byte */ -#define NS_LOSS 0x01 /* Out of 8.3 format */ -#define NS_LFN 0x02 /* Force to create LFN entry */ -#define NS_LAST 0x04 /* Last segment */ -#define NS_BODY 0x08 /* Lower case flag (body) */ -#define NS_EXT 0x10 /* Lower case flag (ext) */ -#define NS_DOT 0x20 /* Dot entry */ +#define NS 11 /* Offset of name status byte */ +#define NS_LOSS 0x01 /* Out of 8.3 format */ +#define NS_LFN 0x02 /* Force to create LFN entry */ +#define NS_LAST 0x04 /* Last segment */ +#define NS_BODY 0x08 /* Lower case flag (body) */ +#define NS_EXT 0x10 /* Lower case flag (ext) */ +#define NS_DOT 0x20 /* Dot entry */ /* FAT sub-type boundaries */ /* Note that the FAT spec by Microsoft says 4085 but Windows works with 4087! */ -#define MIN_FAT16 4086 /* Minimum number of clusters for FAT16 */ -#define MIN_FAT32 65526 /* Minimum number of clusters for FAT32 */ +#define MIN_FAT16 4086 /* Minimum number of clusters for FAT16 */ +#define MIN_FAT32 65526 /* Minimum number of clusters for FAT32 */ /* FatFs refers the members in the FAT structures as byte array instead of / structure member because there are incompatibility of the packing option / between compilers. */ -#define BS_jmpBoot 0 -#define BS_OEMName 3 -#define BPB_BytsPerSec 11 -#define BPB_SecPerClus 13 -#define BPB_RsvdSecCnt 14 -#define BPB_NumFATs 16 -#define BPB_RootEntCnt 17 -#define BPB_TotSec16 19 -#define BPB_Media 21 -#define BPB_FATSz16 22 -#define BPB_SecPerTrk 24 -#define BPB_NumHeads 26 -#define BPB_HiddSec 28 -#define BPB_TotSec32 32 -#define BS_DrvNum 36 -#define BS_BootSig 38 -#define BS_VolID 39 -#define BS_VolLab 43 -#define BS_FilSysType 54 -#define BPB_FATSz32 36 -#define BPB_ExtFlags 40 -#define BPB_FSVer 42 -#define BPB_RootClus 44 -#define BPB_FSInfo 48 -#define BPB_BkBootSec 50 -#define BS_DrvNum32 64 -#define BS_BootSig32 66 -#define BS_VolID32 67 -#define BS_VolLab32 71 -#define BS_FilSysType32 82 -#define FSI_LeadSig 0 -#define FSI_StrucSig 484 -#define FSI_Free_Count 488 -#define FSI_Nxt_Free 492 -#define MBR_Table 446 -#define BS_55AA 510 +#define BS_jmpBoot 0 +#define BS_OEMName 3 +#define BPB_BytsPerSec 11 +#define BPB_SecPerClus 13 +#define BPB_RsvdSecCnt 14 +#define BPB_NumFATs 16 +#define BPB_RootEntCnt 17 +#define BPB_TotSec16 19 +#define BPB_Media 21 +#define BPB_FATSz16 22 +#define BPB_SecPerTrk 24 +#define BPB_NumHeads 26 +#define BPB_HiddSec 28 +#define BPB_TotSec32 32 +#define BS_DrvNum 36 +#define BS_BootSig 38 +#define BS_VolID 39 +#define BS_VolLab 43 +#define BS_FilSysType 54 +#define BPB_FATSz32 36 +#define BPB_ExtFlags 40 +#define BPB_FSVer 42 +#define BPB_RootClus 44 +#define BPB_FSInfo 48 +#define BPB_BkBootSec 50 +#define BS_DrvNum32 64 +#define BS_BootSig32 66 +#define BS_VolID32 67 +#define BS_VolLab32 71 +#define BS_FilSysType32 82 +#define FSI_LeadSig 0 +#define FSI_StrucSig 484 +#define FSI_Free_Count 488 +#define FSI_Nxt_Free 492 +#define MBR_Table 446 +#define BS_55AA 510 -#define DIR_Name 0 -#define DIR_Attr 11 -#define DIR_NTres 12 -#define DIR_CrtTime 14 -#define DIR_CrtDate 16 -#define DIR_FstClusHI 20 -#define DIR_WrtTime 22 -#define DIR_WrtDate 24 -#define DIR_FstClusLO 26 -#define DIR_FileSize 28 -#define LDIR_Ord 0 -#define LDIR_Attr 11 -#define LDIR_Type 12 -#define LDIR_Chksum 13 -#define LDIR_FstClusLO 26 +#define DIR_Name 0 +#define DIR_Attr 11 +#define DIR_NTres 12 +#define DIR_CrtTime 14 +#define DIR_CrtDate 16 +#define DIR_FstClusHI 20 +#define DIR_WrtTime 22 +#define DIR_WrtDate 24 +#define DIR_FstClusLO 26 +#define DIR_FileSize 28 +#define LDIR_Ord 0 +#define LDIR_Attr 11 +#define LDIR_Type 12 +#define LDIR_Chksum 13 +#define LDIR_FstClusLO 26 @@ -253,46 +254,46 @@ typedef struct { #if _VOLUMES static -FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */ +FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */ #else #error Number of drives must not be 0. #endif static -WORD Fsid; /* File system mount ID */ +WORD Fsid; /* File system mount ID */ #if _FS_RPATH static -BYTE CurrVol; /* Current drive */ +BYTE CurrVol; /* Current drive */ #endif #if _FS_SHARE static -FILESEM Files[_FS_SHARE]; /* File lock semaphores */ +FILESEM Files[_FS_SHARE]; /* File lock semaphores */ #endif -#if _USE_LFN == 0 /* No LFN */ -#define DEF_NAMEBUF BYTE sfn[12] -#define INIT_BUF(dobj) (dobj).fn = sfn -#define FREE_BUF() +#if _USE_LFN == 0 /* No LFN */ +#define DEF_NAMEBUF BYTE sfn[12] +#define INIT_BUF(dobj) (dobj).fn = sfn +#define FREE_BUF() -#elif _USE_LFN == 1 /* LFN with static LFN working buffer */ -static WCHAR LfnBuf[_MAX_LFN+1]; -#define DEF_NAMEBUF BYTE sfn[12] -#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; } -#define FREE_BUF() +#elif _USE_LFN == 1 /* LFN with static LFN working buffer */ +static WCHAR LfnBuf[_MAX_LFN + 1]; +#define DEF_NAMEBUF BYTE sfn[12] +#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; } +#define FREE_BUF() -#elif _USE_LFN == 2 /* LFN with dynamic LFN working buffer on the stack */ -#define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1] -#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; } -#define FREE_BUF() +#elif _USE_LFN == 2 /* LFN with dynamic LFN working buffer on the stack */ +#define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1] +#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; } +#define FREE_BUF() -#elif _USE_LFN == 3 /* LFN with dynamic LFN working buffer on the heap */ -#define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn -#define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \ - if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \ - (dobj).lfn = lfn; (dobj).fn = sfn; } -#define FREE_BUF() ff_memfree(lfn) +#elif _USE_LFN == 3 /* LFN with dynamic LFN working buffer on the heap */ +#define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn +#define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \ + if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \ + (dobj).lfn = lfn; (dobj).fn = sfn; } +#define FREE_BUF() ff_memfree(lfn) #else #error Wrong LFN configuration. @@ -313,46 +314,60 @@ static WCHAR LfnBuf[_MAX_LFN+1]; /*-----------------------------------------------------------------------*/ /* Copy memory to memory */ -static -void mem_cpy (void* dst, const void* src, UINT cnt) { - BYTE *d = (BYTE*)dst; - const BYTE *s = (const BYTE*)src; +static void mem_cpy ( void *dst, const void *src, UINT cnt ) +{ + BYTE *d = ( BYTE * )dst; + const BYTE *s = ( const BYTE * )src; #if _WORD_ACCESS == 1 - while (cnt >= sizeof(int)) { - *(int*)d = *(int*)s; - d += sizeof(int); s += sizeof(int); - cnt -= sizeof(int); - } + + while ( cnt >= sizeof( int ) ) + { + *( int * )d = *( int * )s; + d += sizeof( int ); s += sizeof( int ); + cnt -= sizeof( int ); + } + #endif - while (cnt--) - *d++ = *s++; + + while ( cnt-- ) + { + *d++ = *s++; + } } /* Fill memory */ -static -void mem_set (void* dst, int val, UINT cnt) { - BYTE *d = (BYTE*)dst; +static void mem_set ( void *dst, int val, UINT cnt ) +{ + BYTE *d = ( BYTE * )dst; - while (cnt--) - *d++ = (BYTE)val; + while ( cnt-- ) + { + *d++ = ( BYTE )val; + } } /* Compare memory to memory */ -static -int mem_cmp (const void* dst, const void* src, UINT cnt) { - const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src; - int r = 0; +static int mem_cmp ( const void *dst, const void *src, UINT cnt ) +{ + const BYTE *d = ( const BYTE * )dst, *s = ( const BYTE * )src; + int r = 0; - while (cnt-- && (r = *d++ - *s++) == 0) ; - return r; + while ( cnt-- && ( r = *d++ - *s++ ) == 0 ) ; + + return r; } /* Check if chr is contained in the string */ static -int chk_chr (const char* str, int chr) { - while (*str && *str != chr) str++; - return *str; +int chk_chr ( const char *str, int chr ) +{ + while ( *str && *str != chr ) + { + str++; + } + + return *str; } @@ -364,25 +379,26 @@ int chk_chr (const char* str, int chr) { static int lock_fs ( - FATFS *fs /* File system object */ + FATFS *fs /* File system object */ ) { - return ff_req_grant(fs->sobj); + return ff_req_grant( fs->sobj ); } static void unlock_fs ( - FATFS *fs, /* File system object */ - FRESULT res /* Result code to be returned */ + FATFS *fs, /* File system object */ + FRESULT res /* Result code to be returned */ ) { - if (res != FR_NOT_ENABLED && - res != FR_INVALID_DRIVE && - res != FR_INVALID_OBJECT && - res != FR_TIMEOUT) { - ff_rel_grant(fs->sobj); - } + if ( res != FR_NOT_ENABLED && + res != FR_INVALID_DRIVE && + res != FR_INVALID_OBJECT && + res != FR_TIMEOUT ) + { + ff_rel_grant( fs->sobj ); + } } #endif @@ -394,108 +410,154 @@ void unlock_fs ( #if _FS_SHARE static -FRESULT chk_lock ( /* Check if the file can be accessed */ - DIR* dj, /* Directory object pointing the file to be checked */ - int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ +FRESULT chk_lock ( /* Check if the file can be accessed */ + DIR *dj, /* Directory object pointing the file to be checked */ + int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ ) { - UINT i, be; + UINT i, be; - /* Search file semaphore table */ - for (i = be = 0; i < _FS_SHARE; i++) { - if (Files[i].fs) { /* Existing entry */ - if (Files[i].fs == dj->fs && /* Check if the file matched with an open file */ - Files[i].clu == dj->sclust && - Files[i].idx == dj->index) break; - } else { /* Blank entry */ - be++; - } - } - if (i == _FS_SHARE) /* The file is not opened */ - return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */ + /* Search file semaphore table */ + for ( i = be = 0; i < _FS_SHARE; i++ ) + { + if ( Files[i].fs ) /* Existing entry */ + { + if ( Files[i].fs == dj->fs && /* Check if the file matched with an open file */ + Files[i].clu == dj->sclust && + Files[i].idx == dj->index ) + { + break; + } + } + else /* Blank entry */ + { + be++; + } + } - /* The file has been opened. Reject any open against writing file and all write mode open */ - return (acc || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK; + if ( i == _FS_SHARE ) /* The file is not opened */ + { + return ( be || acc == 2 ) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */ + } + + /* The file has been opened. Reject any open against writing file and all write mode open */ + return ( acc || Files[i].ctr == 0x100 ) ? FR_LOCKED : FR_OK; } static -int enq_lock ( /* Check if an entry is available for a new file */ - FATFS* fs /* File system object */ +int enq_lock ( /* Check if an entry is available for a new file */ + FATFS *fs /* File system object */ ) { - UINT i; + UINT i; - for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ; - return (i == _FS_SHARE) ? 0 : 1; + for ( i = 0; i < _FS_SHARE && Files[i].fs; i++ ) ; + + return ( i == _FS_SHARE ) ? 0 : 1; } static -UINT inc_lock ( /* Increment file open counter and returns its index (0:int error) */ - DIR* dj, /* Directory object pointing the file to register or increment */ - int acc /* Desired access mode (0:Read, !0:Write) */ +UINT inc_lock ( /* Increment file open counter and returns its index (0:int error) */ + DIR *dj, /* Directory object pointing the file to register or increment */ + int acc /* Desired access mode (0:Read, !0:Write) */ ) { - UINT i; + UINT i; - for (i = 0; i < _FS_SHARE; i++) { /* Find the file */ - if (Files[i].fs == dj->fs && - Files[i].clu == dj->sclust && - Files[i].idx == dj->index) break; - } + for ( i = 0; i < _FS_SHARE; i++ ) /* Find the file */ + { + if ( Files[i].fs == dj->fs && + Files[i].clu == dj->sclust && + Files[i].idx == dj->index ) + { + break; + } + } - if (i == _FS_SHARE) { /* Not opened. Register it as new. */ - for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ; - if (i == _FS_SHARE) return 0; /* No space to register (int err) */ - Files[i].fs = dj->fs; - Files[i].clu = dj->sclust; - Files[i].idx = dj->index; - Files[i].ctr = 0; - } + if ( i == _FS_SHARE ) /* Not opened. Register it as new. */ + { + for ( i = 0; i < _FS_SHARE && Files[i].fs; i++ ) ; - if (acc && Files[i].ctr) return 0; /* Access violation (int err) */ + if ( i == _FS_SHARE ) + { + return 0; /* No space to register (int err) */ + } - Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ + Files[i].fs = dj->fs; + Files[i].clu = dj->sclust; + Files[i].idx = dj->index; + Files[i].ctr = 0; + } - return i + 1; + if ( acc && Files[i].ctr ) + { + return 0; /* Access violation (int err) */ + } + + Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ + + return i + 1; } static -FRESULT dec_lock ( /* Decrement file open counter */ - UINT i /* Semaphore index */ +FRESULT dec_lock ( /* Decrement file open counter */ + UINT i /* Semaphore index */ ) { - WORD n; - FRESULT res; + WORD n; + FRESULT res; - if (--i < _FS_SHARE) { - n = Files[i].ctr; - if (n == 0x100) n = 0; - if (n) n--; - Files[i].ctr = n; - if (!n) Files[i].fs = 0; - res = FR_OK; - } else { - res = FR_INT_ERR; - } - return res; + if ( --i < _FS_SHARE ) + { + n = Files[i].ctr; + + if ( n == 0x100 ) + { + n = 0; + } + + if ( n ) + { + n--; + } + + Files[i].ctr = n; + + if ( !n ) + { + Files[i].fs = 0; + } + + res = FR_OK; + } + else + { + res = FR_INT_ERR; + } + + return res; } static -void clear_lock ( /* Clear lock entries of the volume */ - FATFS *fs +void clear_lock ( /* Clear lock entries of the volume */ + FATFS *fs ) { - UINT i; + UINT i; - for (i = 0; i < _FS_SHARE; i++) { - if (Files[i].fs == fs) Files[i].fs = 0; - } + for ( i = 0; i < _FS_SHARE; i++ ) + { + if ( Files[i].fs == fs ) + { + Files[i].fs = 0; + } + } } #endif @@ -507,37 +569,54 @@ void clear_lock ( /* Clear lock entries of the volume */ static FRESULT move_window ( - FATFS *fs, /* File system object */ - DWORD sector /* Sector number to make appearance in the fs->win[] */ -) /* Move to zero only writes back dirty window */ + FATFS *fs, /* File system object */ + DWORD sector /* Sector number to make appearance in the fs->win[] */ +) /* Move to zero only writes back dirty window */ { - DWORD wsect; + DWORD wsect; - wsect = fs->winsect; - if (wsect != sector) { /* Changed current window */ + wsect = fs->winsect; + + if ( wsect != sector ) /* Changed current window */ + { #if !_FS_READONLY - if (fs->wflag) { /* Write back dirty window if needed */ - if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK) - return FR_DISK_ERR; - fs->wflag = 0; - if (wsect < (fs->fatbase + fs->fsize)) { /* In FAT area */ - BYTE nf; - for (nf = fs->n_fats; nf > 1; nf--) { /* Reflect the change to all FAT copies */ - wsect += fs->fsize; - disk_write(fs->drv, fs->win, wsect, 1); - } - } - } -#endif - if (sector) { - if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK) - return FR_DISK_ERR; - fs->winsect = sector; - } - } - return FR_OK; + if ( fs->wflag ) /* Write back dirty window if needed */ + { + if ( disk_write( fs->drv, fs->win, wsect, 1 ) != RES_OK ) + { + return FR_DISK_ERR; + } + + fs->wflag = 0; + + if ( wsect < ( fs->fatbase + fs->fsize ) ) /* In FAT area */ + { + BYTE nf; + + for ( nf = fs->n_fats; nf > 1; nf-- ) /* Reflect the change to all FAT copies */ + { + wsect += fs->fsize; + disk_write( fs->drv, fs->win, wsect, 1 ); + } + } + } + +#endif + + if ( sector ) + { + if ( disk_read( fs->drv, fs->win, sector, 1 ) != RES_OK ) + { + return FR_DISK_ERR; + } + + fs->winsect = sector; + } + } + + return FR_OK; } @@ -548,33 +627,39 @@ FRESULT move_window ( /*-----------------------------------------------------------------------*/ #if !_FS_READONLY static -FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */ - FATFS *fs /* File system object */ +FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */ + FATFS *fs /* File system object */ ) { - FRESULT res; + FRESULT res; - res = move_window(fs, 0); - if (res == FR_OK) { - /* Update FSInfo sector if needed */ - if (fs->fs_type == FS_FAT32 && fs->fsi_flag) { - fs->winsect = 0; - mem_set(fs->win, 0, 512); - ST_WORD(fs->win+BS_55AA, 0xAA55); - ST_DWORD(fs->win+FSI_LeadSig, 0x41615252); - ST_DWORD(fs->win+FSI_StrucSig, 0x61417272); - ST_DWORD(fs->win+FSI_Free_Count, fs->free_clust); - ST_DWORD(fs->win+FSI_Nxt_Free, fs->last_clust); - disk_write(fs->drv, fs->win, fs->fsi_sector, 1); - fs->fsi_flag = 0; - } - /* Make sure that no pending write process in the physical drive */ - if (disk_ioctl(fs->drv, CTRL_SYNC, (void*)0) != RES_OK) - res = FR_DISK_ERR; - } + res = move_window( fs, 0 ); - return res; + if ( res == FR_OK ) + { + /* Update FSInfo sector if needed */ + if ( fs->fs_type == FS_FAT32 && fs->fsi_flag ) + { + fs->winsect = 0; + mem_set( fs->win, 0, 512 ); + ST_WORD( fs->win + BS_55AA, 0xAA55 ); + ST_DWORD( fs->win + FSI_LeadSig, 0x41615252 ); + ST_DWORD( fs->win + FSI_StrucSig, 0x61417272 ); + ST_DWORD( fs->win + FSI_Free_Count, fs->free_clust ); + ST_DWORD( fs->win + FSI_Nxt_Free, fs->last_clust ); + disk_write( fs->drv, fs->win, fs->fsi_sector, 1 ); + fs->fsi_flag = 0; + } + + /* Make sure that no pending write process in the physical drive */ + if ( disk_ioctl( fs->drv, CTRL_SYNC, ( void * )0 ) != RES_OK ) + { + res = FR_DISK_ERR; + } + } + + return res; } #endif @@ -586,14 +671,19 @@ FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */ /*-----------------------------------------------------------------------*/ -DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ - FATFS *fs, /* File system object */ - DWORD clst /* Cluster# to be converted */ +DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to be converted */ ) { - clst -= 2; - if (clst >= (fs->n_fatent - 2)) return 0; /* Invalid cluster# */ - return clst * fs->csize + fs->database; + clst -= 2; + + if ( clst >= ( fs->n_fatent - 2 ) ) + { + return 0; /* Invalid cluster# */ + } + + return clst * fs->csize + fs->database; } @@ -604,39 +694,60 @@ DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ /*-----------------------------------------------------------------------*/ -DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */ - FATFS *fs, /* File system object */ - DWORD clst /* Cluster# to get the link information */ +DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to get the link information */ ) { - UINT wc, bc; - BYTE *p; + UINT wc, bc; + BYTE *p; - if (clst < 2 || clst >= fs->n_fatent) /* Chack range */ - return 1; + if ( clst < 2 || clst >= fs->n_fatent ) /* Chack range */ + { + return 1; + } - switch (fs->fs_type) { - case FS_FAT12 : - bc = (UINT)clst; bc += bc / 2; - if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; - wc = fs->win[bc % SS(fs)]; bc++; - if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; - wc |= fs->win[bc % SS(fs)] << 8; - return (clst & 1) ? (wc >> 4) : (wc & 0xFFF); + switch ( fs->fs_type ) + { + case FS_FAT12 : + bc = ( UINT )clst; bc += bc / 2; - case FS_FAT16 : - if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)))) break; - p = &fs->win[clst * 2 % SS(fs)]; - return LD_WORD(p); + if ( move_window( fs, fs->fatbase + ( bc / SS( fs ) ) ) ) + { + break; + } - case FS_FAT32 : - if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)))) break; - p = &fs->win[clst * 4 % SS(fs)]; - return LD_DWORD(p) & 0x0FFFFFFF; - } + wc = fs->win[bc % SS( fs )]; bc++; - return 0xFFFFFFFF; /* An error occurred at the disk I/O layer */ + if ( move_window( fs, fs->fatbase + ( bc / SS( fs ) ) ) ) + { + break; + } + + wc |= fs->win[bc % SS( fs )] << 8; + return ( clst & 1 ) ? ( wc >> 4 ) : ( wc & 0xFFF ); + + case FS_FAT16 : + if ( move_window( fs, fs->fatbase + ( clst / ( SS( fs ) / 2 ) ) ) ) + { + break; + } + + p = &fs->win[clst * 2 % SS( fs )]; + return LD_WORD( p ); + + case FS_FAT32 : + if ( move_window( fs, fs->fatbase + ( clst / ( SS( fs ) / 4 ) ) ) ) + { + break; + } + + p = &fs->win[clst * 4 % SS( fs )]; + return LD_DWORD( p ) & 0x0FFFFFFF; + } + + return 0xFFFFFFFF; /* An error occurred at the disk I/O layer */ } @@ -648,57 +759,82 @@ DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status #if !_FS_READONLY FRESULT put_fat ( - FATFS *fs, /* File system object */ - DWORD clst, /* Cluster# to be changed in range of 2 to fs->n_fatent - 1 */ - DWORD val /* New value to mark the cluster */ + FATFS *fs, /* File system object */ + DWORD clst, /* Cluster# to be changed in range of 2 to fs->n_fatent - 1 */ + DWORD val /* New value to mark the cluster */ ) { - UINT bc; - BYTE *p; - FRESULT res; + UINT bc; + BYTE *p; + FRESULT res; - if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ - res = FR_INT_ERR; + if ( clst < 2 || clst >= fs->n_fatent ) /* Check range */ + { + res = FR_INT_ERR; - } else { - switch (fs->fs_type) { - case FS_FAT12 : - bc = clst; bc += bc / 2; - res = move_window(fs, fs->fatbase + (bc / SS(fs))); - if (res != FR_OK) break; - p = &fs->win[bc % SS(fs)]; - *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; - bc++; - fs->wflag = 1; - res = move_window(fs, fs->fatbase + (bc / SS(fs))); - if (res != FR_OK) break; - p = &fs->win[bc % SS(fs)]; - *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); - break; + } + else + { + switch ( fs->fs_type ) + { + case FS_FAT12 : + bc = clst; bc += bc / 2; + res = move_window( fs, fs->fatbase + ( bc / SS( fs ) ) ); - case FS_FAT16 : - res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); - if (res != FR_OK) break; - p = &fs->win[clst * 2 % SS(fs)]; - ST_WORD(p, (WORD)val); - break; + if ( res != FR_OK ) + { + break; + } - case FS_FAT32 : - res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); - if (res != FR_OK) break; - p = &fs->win[clst * 4 % SS(fs)]; - val |= LD_DWORD(p) & 0xF0000000; - ST_DWORD(p, val); - break; + p = &fs->win[bc % SS( fs )]; + *p = ( clst & 1 ) ? ( ( *p & 0x0F ) | ( ( BYTE )val << 4 ) ) : ( BYTE )val; + bc++; + fs->wflag = 1; + res = move_window( fs, fs->fatbase + ( bc / SS( fs ) ) ); - default : - res = FR_INT_ERR; - } - fs->wflag = 1; - } + if ( res != FR_OK ) + { + break; + } - return res; + p = &fs->win[bc % SS( fs )]; + *p = ( clst & 1 ) ? ( BYTE )( val >> 4 ) : ( ( *p & 0xF0 ) | ( ( BYTE )( val >> 8 ) & 0x0F ) ); + break; + + case FS_FAT16 : + res = move_window( fs, fs->fatbase + ( clst / ( SS( fs ) / 2 ) ) ); + + if ( res != FR_OK ) + { + break; + } + + p = &fs->win[clst * 2 % SS( fs )]; + ST_WORD( p, ( WORD )val ); + break; + + case FS_FAT32 : + res = move_window( fs, fs->fatbase + ( clst / ( SS( fs ) / 4 ) ) ); + + if ( res != FR_OK ) + { + break; + } + + p = &fs->win[clst * 4 % SS( fs )]; + val |= LD_DWORD( p ) & 0xF0000000; + ST_DWORD( p, val ); + break; + + default : + res = FR_INT_ERR; + } + + fs->wflag = 1; + } + + return res; } #endif /* !_FS_READONLY */ @@ -711,47 +847,79 @@ FRESULT put_fat ( #if !_FS_READONLY static FRESULT remove_chain ( - FATFS *fs, /* File system object */ - DWORD clst /* Cluster# to remove a chain from */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to remove a chain from */ ) { - FRESULT res; - DWORD nxt; + FRESULT res; + DWORD nxt; #if _USE_ERASE - DWORD scl = clst, ecl = clst, resion[2]; + DWORD scl = clst, ecl = clst, resion[2]; #endif - if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ - res = FR_INT_ERR; + if ( clst < 2 || clst >= fs->n_fatent ) /* Check range */ + { + res = FR_INT_ERR; + + } + else + { + res = FR_OK; + + while ( clst < fs->n_fatent ) /* Not a last link? */ + { + nxt = get_fat( fs, clst ); /* Get cluster status */ + + if ( nxt == 0 ) + { + break; /* Empty cluster? */ + } + + if ( nxt == 1 ) + { + res = FR_INT_ERR; /* Internal error? */ + break; + } + + if ( nxt == 0xFFFFFFFF ) + { + res = FR_DISK_ERR; /* Disk error? */ + break; + } + + res = put_fat( fs, clst, 0 ); /* Mark the cluster "empty" */ + + if ( res != FR_OK ) + { + break; + } + + if ( fs->free_clust != 0xFFFFFFFF ) /* Update FSInfo */ + { + fs->free_clust++; + fs->fsi_flag = 1; + } - } else { - res = FR_OK; - while (clst < fs->n_fatent) { /* Not a last link? */ - nxt = get_fat(fs, clst); /* Get cluster status */ - if (nxt == 0) break; /* Empty cluster? */ - if (nxt == 1) { res = FR_INT_ERR; break; } /* Internal error? */ - if (nxt == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } /* Disk error? */ - res = put_fat(fs, clst, 0); /* Mark the cluster "empty" */ - if (res != FR_OK) break; - if (fs->free_clust != 0xFFFFFFFF) { /* Update FSInfo */ - fs->free_clust++; - fs->fsi_flag = 1; - } #if _USE_ERASE - if (ecl + 1 == nxt) { /* Next cluster is contiguous */ - ecl = nxt; - } else { /* End of contiguous clusters */ - resion[0] = clust2sect(fs, scl); /* Start sector */ - resion[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */ - disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, resion); /* Erase the block */ - scl = ecl = nxt; - } -#endif - clst = nxt; /* Next cluster */ - } - } - return res; + if ( ecl + 1 == nxt ) /* Next cluster is contiguous */ + { + ecl = nxt; + } + else /* End of contiguous clusters */ + { + resion[0] = clust2sect( fs, scl ); /* Start sector */ + resion[1] = clust2sect( fs, ecl ) + fs->csize - 1; /* End sector */ + disk_ioctl( fs->drv, CTRL_ERASE_SECTOR, resion ); /* Erase the block */ + scl = ecl = nxt; + } + +#endif + clst = nxt; /* Next cluster */ + } + } + + return res; } #endif @@ -763,55 +931,98 @@ FRESULT remove_chain ( /*-----------------------------------------------------------------------*/ #if !_FS_READONLY static -DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ - FATFS *fs, /* File system object */ - DWORD clst /* Cluster# to stretch. 0 means create a new chain. */ +DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to stretch. 0 means create a new chain. */ ) { - DWORD cs, ncl, scl; - FRESULT res; + DWORD cs, ncl, scl; + FRESULT res; - if (clst == 0) { /* Create a new chain */ - scl = fs->last_clust; /* Get suggested start point */ - if (!scl || scl >= fs->n_fatent) scl = 1; - } - else { /* Stretch the current chain */ - cs = get_fat(fs, clst); /* Check the cluster status */ - if (cs < 2) return 1; /* It is an invalid cluster */ - if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */ - scl = clst; - } + if ( clst == 0 ) /* Create a new chain */ + { + scl = fs->last_clust; /* Get suggested start point */ - ncl = scl; /* Start cluster */ - for (;;) { - ncl++; /* Next cluster */ - if (ncl >= fs->n_fatent) { /* Wrap around */ - ncl = 2; - if (ncl > scl) return 0; /* No free cluster */ - } - cs = get_fat(fs, ncl); /* Get the cluster status */ - if (cs == 0) break; /* Found a free cluster */ - if (cs == 0xFFFFFFFF || cs == 1)/* An error occurred */ - return cs; - if (ncl == scl) return 0; /* No free cluster */ - } + if ( !scl || scl >= fs->n_fatent ) + { + scl = 1; + } + } + else /* Stretch the current chain */ + { + cs = get_fat( fs, clst ); /* Check the cluster status */ - res = put_fat(fs, ncl, 0x0FFFFFFF); /* Mark the new cluster "last link" */ - if (res == FR_OK && clst != 0) { - res = put_fat(fs, clst, ncl); /* Link it to the previous one if needed */ - } - if (res == FR_OK) { - fs->last_clust = ncl; /* Update FSINFO */ - if (fs->free_clust != 0xFFFFFFFF) { - fs->free_clust--; - fs->fsi_flag = 1; - } - } else { - ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1; - } + if ( cs < 2 ) + { + return 1; /* It is an invalid cluster */ + } - return ncl; /* Return new cluster number or error code */ + if ( cs < fs->n_fatent ) + { + return cs; /* It is already followed by next cluster */ + } + + scl = clst; + } + + ncl = scl; /* Start cluster */ + + for ( ;; ) + { + ncl++; /* Next cluster */ + + if ( ncl >= fs->n_fatent ) /* Wrap around */ + { + ncl = 2; + + if ( ncl > scl ) + { + return 0; /* No free cluster */ + } + } + + cs = get_fat( fs, ncl ); /* Get the cluster status */ + + if ( cs == 0 ) + { + break; /* Found a free cluster */ + } + + if ( cs == 0xFFFFFFFF || cs == 1 ) /* An error occurred */ + { + return cs; + } + + if ( ncl == scl ) + { + return 0; /* No free cluster */ + } + } + + res = put_fat( fs, ncl, 0x0FFFFFFF ); /* Mark the new cluster "last link" */ + + if ( res == FR_OK && clst != 0 ) + { + res = put_fat( fs, clst, ncl ); /* Link it to the previous one if needed */ + } + + if ( res == FR_OK ) + { + fs->last_clust = ncl; /* Update FSINFO */ + + if ( fs->free_clust != 0xFFFFFFFF ) + { + fs->free_clust--; + fs->fsi_flag = 1; + } + } + else + { + ncl = ( res == FR_DISK_ERR ) ? 0xFFFFFFFF : 1; + } + + return ncl; /* Return new cluster number or error code */ } #endif /* !_FS_READONLY */ @@ -824,43 +1035,66 @@ DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk err static FRESULT dir_sdi ( - DIR *dj, /* Pointer to directory object */ - WORD idx /* Directory index number */ + DIR *dj, /* Pointer to directory object */ + WORD idx /* Directory index number */ ) { - DWORD clst; - WORD ic; + DWORD clst; + WORD ic; - dj->index = idx; - clst = dj->sclust; - if (clst == 1 || clst >= dj->fs->n_fatent) /* Check start cluster range */ - return FR_INT_ERR; - if (!clst && dj->fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */ - clst = dj->fs->dirbase; + dj->index = idx; + clst = dj->sclust; - if (clst == 0) { /* Static table (root-dir in FAT12/16) */ - dj->clust = clst; - if (idx >= dj->fs->n_rootdir) /* Index is out of range */ - return FR_INT_ERR; - dj->sect = dj->fs->dirbase + idx / (SS(dj->fs) / 32); /* Sector# */ - } - else { /* Dynamic table (sub-dirs or root-dir in FAT32) */ - ic = SS(dj->fs) / 32 * dj->fs->csize; /* Entries per cluster */ - while (idx >= ic) { /* Follow cluster chain */ - clst = get_fat(dj->fs, clst); /* Get next cluster */ - if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ - if (clst < 2 || clst >= dj->fs->n_fatent) /* Reached to end of table or int error */ - return FR_INT_ERR; - idx -= ic; - } - dj->clust = clst; - dj->sect = clust2sect(dj->fs, clst) + idx / (SS(dj->fs) / 32); /* Sector# */ - } + if ( clst == 1 || clst >= dj->fs->n_fatent ) /* Check start cluster range */ + { + return FR_INT_ERR; + } - dj->dir = dj->fs->win + (idx % (SS(dj->fs) / 32)) * 32; /* Ptr to the entry in the sector */ + if ( !clst && dj->fs->fs_type == FS_FAT32 ) /* Replace cluster# 0 with root cluster# if in FAT32 */ + { + clst = dj->fs->dirbase; + } - return FR_OK; /* Seek succeeded */ + if ( clst == 0 ) /* Static table (root-dir in FAT12/16) */ + { + dj->clust = clst; + + if ( idx >= dj->fs->n_rootdir ) /* Index is out of range */ + { + return FR_INT_ERR; + } + + dj->sect = dj->fs->dirbase + idx / ( SS( dj->fs ) / 32 ); /* Sector# */ + } + else /* Dynamic table (sub-dirs or root-dir in FAT32) */ + { + ic = SS( dj->fs ) / 32 * dj->fs->csize; /* Entries per cluster */ + + while ( idx >= ic ) /* Follow cluster chain */ + { + clst = get_fat( dj->fs, clst ); /* Get next cluster */ + + if ( clst == 0xFFFFFFFF ) + { + return FR_DISK_ERR; /* Disk error */ + } + + if ( clst < 2 || clst >= dj->fs->n_fatent ) /* Reached to end of table or int error */ + { + return FR_INT_ERR; + } + + idx -= ic; + } + + dj->clust = clst; + dj->sect = clust2sect( dj->fs, clst ) + idx / ( SS( dj->fs ) / 32 ); /* Sector# */ + } + + dj->dir = dj->fs->win + ( idx % ( SS( dj->fs ) / 32 ) ) * 32; /* Ptr to the entry in the sector */ + + return FR_OK; /* Seek succeeded */ } @@ -871,63 +1105,113 @@ FRESULT dir_sdi ( /*-----------------------------------------------------------------------*/ static -FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT and could not stretch */ - DIR *dj, /* Pointer to directory object */ - int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ +FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT and could not stretch */ + DIR *dj, /* Pointer to directory object */ + int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ ) { - DWORD clst; - WORD i; + DWORD clst; + WORD i; - i = dj->index + 1; - if (!i || !dj->sect) /* Report EOT when index has reached 65535 */ - return FR_NO_FILE; + i = dj->index + 1; - if (!(i % (SS(dj->fs) / 32))) { /* Sector changed? */ - dj->sect++; /* Next sector */ + if ( !i || !dj->sect ) /* Report EOT when index has reached 65535 */ + { + return FR_NO_FILE; + } - if (dj->clust == 0) { /* Static table */ - if (i >= dj->fs->n_rootdir) /* Report EOT when end of table */ - return FR_NO_FILE; - } - else { /* Dynamic table */ - if (((i / (SS(dj->fs) / 32)) & (dj->fs->csize - 1)) == 0) { /* Cluster changed? */ - clst = get_fat(dj->fs, dj->clust); /* Get next cluster */ - if (clst <= 1) return FR_INT_ERR; - if (clst == 0xFFFFFFFF) return FR_DISK_ERR; - if (clst >= dj->fs->n_fatent) { /* When it reached end of dynamic table */ + if ( !( i % ( SS( dj->fs ) / 32 ) ) ) /* Sector changed? */ + { + dj->sect++; /* Next sector */ + + if ( dj->clust == 0 ) /* Static table */ + { + if ( i >= dj->fs->n_rootdir ) /* Report EOT when end of table */ + { + return FR_NO_FILE; + } + } + else /* Dynamic table */ + { + if ( ( ( i / ( SS( dj->fs ) / 32 ) ) & ( dj->fs->csize - 1 ) ) == 0 ) /* Cluster changed? */ + { + clst = get_fat( dj->fs, dj->clust ); /* Get next cluster */ + + if ( clst <= 1 ) + { + return FR_INT_ERR; + } + + if ( clst == 0xFFFFFFFF ) + { + return FR_DISK_ERR; + } + + if ( clst >= dj->fs->n_fatent ) /* When it reached end of dynamic table */ + { #if !_FS_READONLY - BYTE c; - if (!stretch) return FR_NO_FILE; /* When do not stretch, report EOT */ - clst = create_chain(dj->fs, dj->clust); /* Stretch cluster chain */ - if (clst == 0) return FR_DENIED; /* No free cluster */ - if (clst == 1) return FR_INT_ERR; - if (clst == 0xFFFFFFFF) return FR_DISK_ERR; - /* Clean-up stretched table */ - if (move_window(dj->fs, 0)) return FR_DISK_ERR; /* Flush active window */ - mem_set(dj->fs->win, 0, SS(dj->fs)); /* Clear window buffer */ - dj->fs->winsect = clust2sect(dj->fs, clst); /* Cluster start sector */ - for (c = 0; c < dj->fs->csize; c++) { /* Fill the new cluster with 0 */ - dj->fs->wflag = 1; - if (move_window(dj->fs, 0)) return FR_DISK_ERR; - dj->fs->winsect++; - } - dj->fs->winsect -= c; /* Rewind window address */ + BYTE c; + + if ( !stretch ) + { + return FR_NO_FILE; /* When do not stretch, report EOT */ + } + + clst = create_chain( dj->fs, dj->clust ); /* Stretch cluster chain */ + + if ( clst == 0 ) + { + return FR_DENIED; /* No free cluster */ + } + + if ( clst == 1 ) + { + return FR_INT_ERR; + } + + if ( clst == 0xFFFFFFFF ) + { + return FR_DISK_ERR; + } + + /* Clean-up stretched table */ + if ( move_window( dj->fs, 0 ) ) + { + return FR_DISK_ERR; /* Flush active window */ + } + + mem_set( dj->fs->win, 0, SS( dj->fs ) ); /* Clear window buffer */ + dj->fs->winsect = clust2sect( dj->fs, clst ); /* Cluster start sector */ + + for ( c = 0; c < dj->fs->csize; c++ ) /* Fill the new cluster with 0 */ + { + dj->fs->wflag = 1; + + if ( move_window( dj->fs, 0 ) ) + { + return FR_DISK_ERR; + } + + dj->fs->winsect++; + } + + dj->fs->winsect -= c; /* Rewind window address */ #else - return FR_NO_FILE; /* Report EOT */ + return FR_NO_FILE; /* Report EOT */ #endif - } - dj->clust = clst; /* Initialize data for new cluster */ - dj->sect = clust2sect(dj->fs, clst); - } - } - } + } - dj->index = i; - dj->dir = dj->fs->win + (i % (SS(dj->fs) / 32)) * 32; + dj->clust = clst; /* Initialize data for new cluster */ + dj->sect = clust2sect( dj->fs, clst ); + } + } + } - return FR_OK; + dj->index = i; + dj->dir = dj->fs->win + ( i % ( SS( dj->fs ) / 32 ) ) * 32; + + return FR_OK; } @@ -938,99 +1222,149 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an /*-----------------------------------------------------------------------*/ #if _USE_LFN static -const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* Offset of LFN chars in the directory entry */ +const BYTE LfnOfs[] = {1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30}; /* Offset of LFN chars in the directory entry */ static -int cmp_lfn ( /* 1:Matched, 0:Not matched */ - WCHAR *lfnbuf, /* Pointer to the LFN to be compared */ - BYTE *dir /* Pointer to the directory entry containing a part of LFN */ +int cmp_lfn ( /* 1:Matched, 0:Not matched */ + WCHAR *lfnbuf, /* Pointer to the LFN to be compared */ + BYTE *dir /* Pointer to the directory entry containing a part of LFN */ ) { - UINT i, s; - WCHAR wc, uc; + UINT i, s; + WCHAR wc, uc; - i = ((dir[LDIR_Ord] & 0xBF) - 1) * 13; /* Get offset in the LFN buffer */ - s = 0; wc = 1; - do { - uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */ - if (wc) { /* Last char has not been processed */ - wc = ff_wtoupper(uc); /* Convert it to upper case */ - if (i >= _MAX_LFN || wc != ff_wtoupper(lfnbuf[i++])) /* Compare it */ - return 0; /* Not matched */ - } else { - if (uc != 0xFFFF) return 0; /* Check filler */ - } - } while (++s < 13); /* Repeat until all chars in the entry are checked */ + i = ( ( dir[LDIR_Ord] & 0xBF ) - 1 ) * 13; /* Get offset in the LFN buffer */ + s = 0; wc = 1; - if ((dir[LDIR_Ord] & 0x40) && wc && lfnbuf[i]) /* Last segment matched but different length */ - return 0; + do + { + uc = LD_WORD( dir + LfnOfs[s] ); /* Pick an LFN character from the entry */ - return 1; /* The part of LFN matched */ + if ( wc ) /* Last char has not been processed */ + { + wc = ff_wtoupper( uc ); /* Convert it to upper case */ + + if ( i >= _MAX_LFN || wc != ff_wtoupper( lfnbuf[i++] ) ) /* Compare it */ + { + return 0; /* Not matched */ + } + } + else + { + if ( uc != 0xFFFF ) + { + return 0; /* Check filler */ + } + } + } + while ( ++s < 13 ); /* Repeat until all chars in the entry are checked */ + + if ( ( dir[LDIR_Ord] & 0x40 ) && wc && lfnbuf[i] ) /* Last segment matched but different length */ + { + return 0; + } + + return 1; /* The part of LFN matched */ } static -int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */ - WCHAR *lfnbuf, /* Pointer to the Unicode-LFN buffer */ - BYTE *dir /* Pointer to the directory entry */ +int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */ + WCHAR *lfnbuf, /* Pointer to the Unicode-LFN buffer */ + BYTE *dir /* Pointer to the directory entry */ ) { - UINT i, s; - WCHAR wc, uc; + UINT i, s; + WCHAR wc, uc; - i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */ + i = ( ( dir[LDIR_Ord] & 0x3F ) - 1 ) * 13; /* Offset in the LFN buffer */ - s = 0; wc = 1; - do { - uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */ - if (wc) { /* Last char has not been processed */ - if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ - lfnbuf[i++] = wc = uc; /* Store it */ - } else { - if (uc != 0xFFFF) return 0; /* Check filler */ - } - } while (++s < 13); /* Read all character in the entry */ + s = 0; wc = 1; - if (dir[LDIR_Ord] & 0x40) { /* Put terminator if it is the last LFN part */ - if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ - lfnbuf[i] = 0; - } + do + { + uc = LD_WORD( dir + LfnOfs[s] ); /* Pick an LFN character from the entry */ - return 1; + if ( wc ) /* Last char has not been processed */ + { + if ( i >= _MAX_LFN ) + { + return 0; /* Buffer overflow? */ + } + + lfnbuf[i++] = wc = uc; /* Store it */ + } + else + { + if ( uc != 0xFFFF ) + { + return 0; /* Check filler */ + } + } + } + while ( ++s < 13 ); /* Read all character in the entry */ + + if ( dir[LDIR_Ord] & 0x40 ) /* Put terminator if it is the last LFN part */ + { + if ( i >= _MAX_LFN ) + { + return 0; /* Buffer overflow? */ + } + + lfnbuf[i] = 0; + } + + return 1; } #if !_FS_READONLY static void fit_lfn ( - const WCHAR *lfnbuf, /* Pointer to the LFN buffer */ - BYTE *dir, /* Pointer to the directory entry */ - BYTE ord, /* LFN order (1-20) */ - BYTE sum /* SFN sum */ + const WCHAR *lfnbuf, /* Pointer to the LFN buffer */ + BYTE *dir, /* Pointer to the directory entry */ + BYTE ord, /* LFN order (1-20) */ + BYTE sum /* SFN sum */ ) { - UINT i, s; - WCHAR wc; + UINT i, s; + WCHAR wc; - dir[LDIR_Chksum] = sum; /* Set check sum */ - dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */ - dir[LDIR_Type] = 0; - ST_WORD(dir+LDIR_FstClusLO, 0); + dir[LDIR_Chksum] = sum; /* Set check sum */ + dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */ + dir[LDIR_Type] = 0; + ST_WORD( dir + LDIR_FstClusLO, 0 ); - i = (ord - 1) * 13; /* Get offset in the LFN buffer */ - s = wc = 0; - do { - if (wc != 0xFFFF) wc = lfnbuf[i++]; /* Get an effective char */ - ST_WORD(dir+LfnOfs[s], wc); /* Put it */ - if (!wc) wc = 0xFFFF; /* Padding chars following last char */ - } while (++s < 13); - if (wc == 0xFFFF || !lfnbuf[i]) ord |= 0x40; /* Bottom LFN part is the start of LFN sequence */ - dir[LDIR_Ord] = ord; /* Set the LFN order */ + i = ( ord - 1 ) * 13; /* Get offset in the LFN buffer */ + s = wc = 0; + + do + { + if ( wc != 0xFFFF ) + { + wc = lfnbuf[i++]; /* Get an effective char */ + } + + ST_WORD( dir + LfnOfs[s], wc ); /* Put it */ + + if ( !wc ) + { + wc = 0xFFFF; /* Padding chars following last char */ + } + } + while ( ++s < 13 ); + + if ( wc == 0xFFFF || !lfnbuf[i] ) + { + ord |= 0x40; /* Bottom LFN part is the start of LFN sequence */ + } + + dir[LDIR_Ord] = ord; /* Set the LFN order */ } #endif @@ -1043,42 +1377,65 @@ void fit_lfn ( /*-----------------------------------------------------------------------*/ #if _USE_LFN void gen_numname ( - BYTE *dst, /* Pointer to generated SFN */ - const BYTE *src, /* Pointer to source SFN to be modified */ - const WCHAR *lfn, /* Pointer to LFN */ - WORD seq /* Sequence number */ + BYTE *dst, /* Pointer to generated SFN */ + const BYTE *src, /* Pointer to source SFN to be modified */ + const WCHAR *lfn, /* Pointer to LFN */ + WORD seq /* Sequence number */ ) { - BYTE ns[8], c; - UINT i, j; + BYTE ns[8], c; + UINT i, j; - mem_cpy(dst, src, 11); + mem_cpy( dst, src, 11 ); - if (seq > 5) { /* On many collisions, generate a hash number instead of sequential number */ - do seq = (seq >> 1) + (seq << 15) + (WORD)*lfn++; while (*lfn); - } + if ( seq > 5 ) /* On many collisions, generate a hash number instead of sequential number */ + { + do + { + seq = ( seq >> 1 ) + ( seq << 15 ) + ( WORD ) * lfn++; + } + while ( *lfn ); + } - /* itoa */ - i = 7; - do { - c = (seq % 16) + '0'; - if (c > '9') c += 7; - ns[i--] = c; - seq /= 16; - } while (seq); - ns[i] = '~'; + /* itoa */ + i = 7; - /* Append the number */ - for (j = 0; j < i && dst[j] != ' '; j++) { - if (IsDBCS1(dst[j])) { - if (j == i - 1) break; - j++; - } - } - do { - dst[j++] = (i < 8) ? ns[i++] : ' '; - } while (j < 8); + do + { + c = ( seq % 16 ) + '0'; + + if ( c > '9' ) + { + c += 7; + } + + ns[i--] = c; + seq /= 16; + } + while ( seq ); + + ns[i] = '~'; + + /* Append the number */ + for ( j = 0; j < i && dst[j] != ' '; j++ ) + { + if ( IsDBCS1( dst[j] ) ) + { + if ( j == i - 1 ) + { + break; + } + + j++; + } + } + + do + { + dst[j++] = ( i < 8 ) ? ns[i++] : ' '; + } + while ( j < 8 ); } #endif @@ -1091,14 +1448,19 @@ void gen_numname ( #if _USE_LFN static BYTE sum_sfn ( - const BYTE *dir /* Ptr to directory entry */ + const BYTE *dir /* Ptr to directory entry */ ) { - BYTE sum = 0; - UINT n = 11; + BYTE sum = 0; + UINT n = 11; - do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n); - return sum; + do + { + sum = ( sum >> 1 ) + ( sum << 7 ) + *dir++; + } + while ( --n ); + + return sum; } #endif @@ -1111,56 +1473,97 @@ BYTE sum_sfn ( static FRESULT dir_find ( - DIR *dj /* Pointer to the directory object linked to the file name */ + DIR *dj /* Pointer to the directory object linked to the file name */ ) { - FRESULT res; - BYTE c, *dir; + FRESULT res; + BYTE c, *dir; #if _USE_LFN - BYTE a, ord, sum; + BYTE a, ord, sum; #endif - res = dir_sdi(dj, 0); /* Rewind directory object */ - if (res != FR_OK) return res; + res = dir_sdi( dj, 0 ); /* Rewind directory object */ + + if ( res != FR_OK ) + { + return res; + } #if _USE_LFN - ord = sum = 0xFF; + ord = sum = 0xFF; #endif - do { - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - dir = dj->dir; /* Ptr to the directory entry of current index */ - c = dir[DIR_Name]; - if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ -#if _USE_LFN /* LFN configuration */ - a = dir[DIR_Attr] & AM_MASK; - if (c == 0xE5 || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ - ord = 0xFF; - } else { - if (a == AM_LFN) { /* An LFN entry is found */ - if (dj->lfn) { - if (c & 0x40) { /* Is it start of LFN sequence? */ - sum = dir[LDIR_Chksum]; - c &= 0xBF; ord = c; /* LFN start order */ - dj->lfn_idx = dj->index; - } - /* Check validity of the LFN entry and compare it with given name */ - ord = (c == ord && sum == dir[LDIR_Chksum] && cmp_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF; - } - } else { /* An SFN entry is found */ - if (!ord && sum == sum_sfn(dir)) break; /* LFN matched? */ - ord = 0xFF; dj->lfn_idx = 0xFFFF; /* Reset LFN sequence */ - if (!(dj->fn[NS] & NS_LOSS) && !mem_cmp(dir, dj->fn, 11)) break; /* SFN matched? */ - } - } -#else /* Non LFN configuration */ - if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */ - break; -#endif - res = dir_next(dj, 0); /* Next entry */ - } while (res == FR_OK); - return res; + do + { + res = move_window( dj->fs, dj->sect ); + + if ( res != FR_OK ) + { + break; + } + + dir = dj->dir; /* Ptr to the directory entry of current index */ + c = dir[DIR_Name]; + + if ( c == 0 ) + { + res = FR_NO_FILE; /* Reached to end of table */ + break; + } + +#if _USE_LFN /* LFN configuration */ + a = dir[DIR_Attr] & AM_MASK; + + if ( c == 0xE5 || ( ( a & AM_VOL ) && a != AM_LFN ) ) /* An entry without valid data */ + { + ord = 0xFF; + } + else + { + if ( a == AM_LFN ) /* An LFN entry is found */ + { + if ( dj->lfn ) + { + if ( c & 0x40 ) /* Is it start of LFN sequence? */ + { + sum = dir[LDIR_Chksum]; + c &= 0xBF; ord = c; /* LFN start order */ + dj->lfn_idx = dj->index; + } + + /* Check validity of the LFN entry and compare it with given name */ + ord = ( c == ord && sum == dir[LDIR_Chksum] && cmp_lfn( dj->lfn, dir ) ) ? ord - 1 : 0xFF; + } + } + else /* An SFN entry is found */ + { + if ( !ord && sum == sum_sfn( dir ) ) + { + break; /* LFN matched? */ + } + + ord = 0xFF; dj->lfn_idx = 0xFFFF; /* Reset LFN sequence */ + + if ( !( dj->fn[NS] & NS_LOSS ) && !mem_cmp( dir, dj->fn, 11 ) ) + { + break; /* SFN matched? */ + } + } + } + +#else /* Non LFN configuration */ + + if ( !( dir[DIR_Attr] & AM_VOL ) && !mem_cmp( dir, dj->fn, 11 ) ) /* Is it a valid entry? */ + { + break; + } + +#endif + res = dir_next( dj, 0 ); /* Next entry */ + } + while ( res == FR_OK ); + + return res; } @@ -1172,52 +1575,89 @@ FRESULT dir_find ( #if _FS_MINIMIZE <= 1 static FRESULT dir_read ( - DIR *dj /* Pointer to the directory object that pointing the entry to be read */ + DIR *dj /* Pointer to the directory object that pointing the entry to be read */ ) { - FRESULT res; - BYTE c, *dir; + FRESULT res; + BYTE c, *dir; #if _USE_LFN - BYTE a, ord = 0xFF, sum = 0xFF; + BYTE a, ord = 0xFF, sum = 0xFF; #endif - res = FR_NO_FILE; - while (dj->sect) { - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - dir = dj->dir; /* Ptr to the directory entry of current index */ - c = dir[DIR_Name]; - if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ -#if _USE_LFN /* LFN configuration */ - a = dir[DIR_Attr] & AM_MASK; - if (c == 0xE5 || (!_FS_RPATH && c == '.') || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ - ord = 0xFF; - } else { - if (a == AM_LFN) { /* An LFN entry is found */ - if (c & 0x40) { /* Is it start of LFN sequence? */ - sum = dir[LDIR_Chksum]; - c &= 0xBF; ord = c; - dj->lfn_idx = dj->index; - } - /* Check LFN validity and capture it */ - ord = (c == ord && sum == dir[LDIR_Chksum] && pick_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF; - } else { /* An SFN entry is found */ - if (ord || sum != sum_sfn(dir)) /* Is there a valid LFN? */ - dj->lfn_idx = 0xFFFF; /* It has no LFN. */ - break; - } - } -#else /* Non LFN configuration */ - if (c != 0xE5 && (_FS_RPATH || c != '.') && !(dir[DIR_Attr] & AM_VOL)) /* Is it a valid entry? */ - break; + res = FR_NO_FILE; + + while ( dj->sect ) + { + res = move_window( dj->fs, dj->sect ); + + if ( res != FR_OK ) + { + break; + } + + dir = dj->dir; /* Ptr to the directory entry of current index */ + c = dir[DIR_Name]; + + if ( c == 0 ) + { + res = FR_NO_FILE; /* Reached to end of table */ + break; + } + +#if _USE_LFN /* LFN configuration */ + a = dir[DIR_Attr] & AM_MASK; + + if ( c == 0xE5 || ( !_FS_RPATH && c == '.' ) || ( ( a & AM_VOL ) && a != AM_LFN ) ) /* An entry without valid data */ + { + ord = 0xFF; + } + else + { + if ( a == AM_LFN ) /* An LFN entry is found */ + { + if ( c & 0x40 ) /* Is it start of LFN sequence? */ + { + sum = dir[LDIR_Chksum]; + c &= 0xBF; ord = c; + dj->lfn_idx = dj->index; + } + + /* Check LFN validity and capture it */ + ord = ( c == ord && sum == dir[LDIR_Chksum] && pick_lfn( dj->lfn, dir ) ) ? ord - 1 : 0xFF; + } + else /* An SFN entry is found */ + { + if ( ord || sum != sum_sfn( dir ) ) /* Is there a valid LFN? */ + { + dj->lfn_idx = 0xFFFF; /* It has no LFN. */ + } + + break; + } + } + +#else /* Non LFN configuration */ + + if ( c != 0xE5 && ( _FS_RPATH || c != '.' ) && !( dir[DIR_Attr] & AM_VOL ) ) /* Is it a valid entry? */ + { + break; + } + #endif - res = dir_next(dj, 0); /* Next entry */ - if (res != FR_OK) break; - } + res = dir_next( dj, 0 ); /* Next entry */ - if (res != FR_OK) dj->sect = 0; + if ( res != FR_OK ) + { + break; + } + } - return res; + if ( res != FR_OK ) + { + dj->sect = 0; + } + + return res; } #endif @@ -1228,102 +1668,178 @@ FRESULT dir_read ( /*-----------------------------------------------------------------------*/ #if !_FS_READONLY static -FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many SFN collision, FR_DISK_ERR:Disk error */ - DIR *dj /* Target directory with object name to be created */ +FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many SFN collision, FR_DISK_ERR:Disk error */ + DIR *dj /* Target directory with object name to be created */ ) { - FRESULT res; - BYTE c, *dir; -#if _USE_LFN /* LFN configuration */ - WORD n, ne, is; - BYTE sn[12], *fn, sum; - WCHAR *lfn; + FRESULT res; + BYTE c, *dir; +#if _USE_LFN /* LFN configuration */ + WORD n, ne, is; + BYTE sn[12], *fn, sum; + WCHAR *lfn; - fn = dj->fn; lfn = dj->lfn; - mem_cpy(sn, fn, 12); + fn = dj->fn; lfn = dj->lfn; + mem_cpy( sn, fn, 12 ); - if (_FS_RPATH && (sn[NS] & NS_DOT)) /* Cannot create dot entry */ - return FR_INVALID_NAME; + if ( _FS_RPATH && ( sn[NS] & NS_DOT ) ) /* Cannot create dot entry */ + { + return FR_INVALID_NAME; + } - if (sn[NS] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ - fn[NS] = 0; dj->lfn = 0; /* Find only SFN */ - for (n = 1; n < 100; n++) { - gen_numname(fn, sn, lfn, n); /* Generate a numbered name */ - res = dir_find(dj); /* Check if the name collides with existing SFN */ - if (res != FR_OK) break; - } - if (n == 100) return FR_DENIED; /* Abort if too many collisions */ - if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */ - fn[NS] = sn[NS]; dj->lfn = lfn; - } + if ( sn[NS] & NS_LOSS ) /* When LFN is out of 8.3 format, generate a numbered name */ + { + fn[NS] = 0; dj->lfn = 0; /* Find only SFN */ - if (sn[NS] & NS_LFN) { /* When LFN is to be created, reserve an SFN + LFN entries. */ - for (ne = 0; lfn[ne]; ne++) ; - ne = (ne + 25) / 13; - } else { /* Otherwise reserve only an SFN entry. */ - ne = 1; - } + for ( n = 1; n < 100; n++ ) + { + gen_numname( fn, sn, lfn, n ); /* Generate a numbered name */ + res = dir_find( dj ); /* Check if the name collides with existing SFN */ - /* Reserve contiguous entries */ - res = dir_sdi(dj, 0); - if (res != FR_OK) return res; - n = is = 0; - do { - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - c = *dj->dir; /* Check the entry status */ - if (c == 0xE5 || c == 0) { /* Is it a blank entry? */ - if (n == 0) is = dj->index; /* First index of the contiguous entry */ - if (++n == ne) break; /* A contiguous entry that required count is found */ - } else { - n = 0; /* Not a blank entry. Restart to search */ - } - res = dir_next(dj, 1); /* Next entry with table stretch */ - } while (res == FR_OK); + if ( res != FR_OK ) + { + break; + } + } - if (res == FR_OK && ne > 1) { /* Initialize LFN entry if needed */ - res = dir_sdi(dj, is); - if (res == FR_OK) { - sum = sum_sfn(dj->fn); /* Sum of the SFN tied to the LFN */ - ne--; - do { /* Store LFN entries in bottom first */ - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - fit_lfn(dj->lfn, dj->dir, (BYTE)ne, sum); - dj->fs->wflag = 1; - res = dir_next(dj, 0); /* Next entry */ - } while (res == FR_OK && --ne); - } - } + if ( n == 100 ) + { + return FR_DENIED; /* Abort if too many collisions */ + } + + if ( res != FR_NO_FILE ) + { + return res; /* Abort if the result is other than 'not collided' */ + } + + fn[NS] = sn[NS]; dj->lfn = lfn; + } + + if ( sn[NS] & NS_LFN ) /* When LFN is to be created, reserve an SFN + LFN entries. */ + { + for ( ne = 0; lfn[ne]; ne++ ) ; + + ne = ( ne + 25 ) / 13; + } + else /* Otherwise reserve only an SFN entry. */ + { + ne = 1; + } + + /* Reserve contiguous entries */ + res = dir_sdi( dj, 0 ); + + if ( res != FR_OK ) + { + return res; + } + + n = is = 0; + + do + { + res = move_window( dj->fs, dj->sect ); + + if ( res != FR_OK ) + { + break; + } + + c = *dj->dir; /* Check the entry status */ + + if ( c == 0xE5 || c == 0 ) /* Is it a blank entry? */ + { + if ( n == 0 ) + { + is = dj->index; /* First index of the contiguous entry */ + } + + if ( ++n == ne ) + { + break; /* A contiguous entry that required count is found */ + } + } + else + { + n = 0; /* Not a blank entry. Restart to search */ + } + + res = dir_next( dj, 1 ); /* Next entry with table stretch */ + } + while ( res == FR_OK ); + + if ( res == FR_OK && ne > 1 ) /* Initialize LFN entry if needed */ + { + res = dir_sdi( dj, is ); + + if ( res == FR_OK ) + { + sum = sum_sfn( dj->fn ); /* Sum of the SFN tied to the LFN */ + ne--; + + do /* Store LFN entries in bottom first */ + { + res = move_window( dj->fs, dj->sect ); + + if ( res != FR_OK ) + { + break; + } + + fit_lfn( dj->lfn, dj->dir, ( BYTE )ne, sum ); + dj->fs->wflag = 1; + res = dir_next( dj, 0 ); /* Next entry */ + } + while ( res == FR_OK && --ne ); + } + } + +#else /* Non LFN configuration */ + res = dir_sdi( dj, 0 ); + + if ( res == FR_OK ) + { + do /* Find a blank entry for the SFN */ + { + res = move_window( dj->fs, dj->sect ); + + if ( res != FR_OK ) + { + break; + } + + c = *dj->dir; + + if ( c == 0xE5 || c == 0 ) + { + break; /* Is it a blank entry? */ + } + + res = dir_next( dj, 1 ); /* Next entry with table stretch */ + } + while ( res == FR_OK ); + } -#else /* Non LFN configuration */ - res = dir_sdi(dj, 0); - if (res == FR_OK) { - do { /* Find a blank entry for the SFN */ - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - c = *dj->dir; - if (c == 0xE5 || c == 0) break; /* Is it a blank entry? */ - res = dir_next(dj, 1); /* Next entry with table stretch */ - } while (res == FR_OK); - } #endif - if (res == FR_OK) { /* Initialize the SFN entry */ - res = move_window(dj->fs, dj->sect); - if (res == FR_OK) { - dir = dj->dir; - mem_set(dir, 0, 32); /* Clean the entry */ - mem_cpy(dir, dj->fn, 11); /* Put SFN */ + if ( res == FR_OK ) /* Initialize the SFN entry */ + { + res = move_window( dj->fs, dj->sect ); + + if ( res == FR_OK ) + { + dir = dj->dir; + mem_set( dir, 0, 32 ); /* Clean the entry */ + mem_cpy( dir, dj->fn, 11 ); /* Put SFN */ #if _USE_LFN - dir[DIR_NTres] = *(dj->fn+NS) & (NS_BODY | NS_EXT); /* Put NT flag */ + dir[DIR_NTres] = *( dj->fn + NS ) & ( NS_BODY | NS_EXT ); /* Put NT flag */ #endif - dj->fs->wflag = 1; - } - } + dj->fs->wflag = 1; + } + } - return res; + return res; } #endif /* !_FS_READONLY */ @@ -1335,40 +1851,64 @@ FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many /*-----------------------------------------------------------------------*/ #if !_FS_READONLY && !_FS_MINIMIZE static -FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ - DIR *dj /* Directory object pointing the entry to be removed */ +FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ + DIR *dj /* Directory object pointing the entry to be removed */ ) { - FRESULT res; -#if _USE_LFN /* LFN configuration */ - WORD i; + FRESULT res; +#if _USE_LFN /* LFN configuration */ + WORD i; - i = dj->index; /* SFN index */ - res = dir_sdi(dj, (WORD)((dj->lfn_idx == 0xFFFF) ? i : dj->lfn_idx)); /* Goto the SFN or top of the LFN entries */ - if (res == FR_OK) { - do { - res = move_window(dj->fs, dj->sect); - if (res != FR_OK) break; - *dj->dir = 0xE5; /* Mark the entry "deleted" */ - dj->fs->wflag = 1; - if (dj->index >= i) break; /* When reached SFN, all entries of the object has been deleted. */ - res = dir_next(dj, 0); /* Next entry */ - } while (res == FR_OK); - if (res == FR_NO_FILE) res = FR_INT_ERR; - } + i = dj->index; /* SFN index */ + res = dir_sdi( dj, ( WORD )( ( dj->lfn_idx == 0xFFFF ) ? i : + dj->lfn_idx ) ); /* Goto the SFN or top of the LFN entries */ + + if ( res == FR_OK ) + { + do + { + res = move_window( dj->fs, dj->sect ); + + if ( res != FR_OK ) + { + break; + } + + *dj->dir = 0xE5; /* Mark the entry "deleted" */ + dj->fs->wflag = 1; + + if ( dj->index >= i ) + { + break; /* When reached SFN, all entries of the object has been deleted. */ + } + + res = dir_next( dj, 0 ); /* Next entry */ + } + while ( res == FR_OK ); + + if ( res == FR_NO_FILE ) + { + res = FR_INT_ERR; + } + } + +#else /* Non LFN configuration */ + res = dir_sdi( dj, dj->index ); + + if ( res == FR_OK ) + { + res = move_window( dj->fs, dj->sect ); + + if ( res == FR_OK ) + { + *dj->dir = 0xE5; /* Mark the entry "deleted" */ + dj->fs->wflag = 1; + } + } -#else /* Non LFN configuration */ - res = dir_sdi(dj, dj->index); - if (res == FR_OK) { - res = move_window(dj->fs, dj->sect); - if (res == FR_OK) { - *dj->dir = 0xE5; /* Mark the entry "deleted" */ - dj->fs->wflag = 1; - } - } #endif - return res; + return res; } #endif /* !_FS_READONLY */ @@ -1381,208 +1921,381 @@ FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ static FRESULT create_name ( - DIR *dj, /* Pointer to the directory object */ - const TCHAR **path /* Pointer to pointer to the segment in the path string */ + DIR *dj, /* Pointer to the directory object */ + const TCHAR **path /* Pointer to pointer to the segment in the path string */ ) { #ifdef _EXCVT - static const BYTE excvt[] = _EXCVT; /* Upper conversion table for extended chars */ + static const BYTE excvt[] = _EXCVT; /* Upper conversion table for extended chars */ #endif -#if _USE_LFN /* LFN configuration */ - BYTE b, cf; - WCHAR w, *lfn; - UINT i, ni, si, di; - const TCHAR *p; +#if _USE_LFN /* LFN configuration */ + BYTE b, cf; + WCHAR w, *lfn; + UINT i, ni, si, di; + const TCHAR *p; + + /* Create LFN in Unicode */ + si = di = 0; + p = *path; + lfn = dj->lfn; + + for ( ;; ) + { + w = p[si++]; /* Get a character */ + + if ( w < ' ' || w == '/' || w == '\\' ) + { + break; /* Break on end of segment */ + } + + if ( di >= _MAX_LFN ) /* Reject too long name */ + { + return FR_INVALID_NAME; + } - /* Create LFN in Unicode */ - si = di = 0; - p = *path; - lfn = dj->lfn; - for (;;) { - w = p[si++]; /* Get a character */ - if (w < ' ' || w == '/' || w == '\\') break; /* Break on end of segment */ - if (di >= _MAX_LFN) /* Reject too long name */ - return FR_INVALID_NAME; #if !_LFN_UNICODE - w &= 0xFF; - if (IsDBCS1(w)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ - b = (BYTE)p[si++]; /* Get 2nd byte */ - if (!IsDBCS2(b)) - return FR_INVALID_NAME; /* Reject invalid sequence */ - w = (w << 8) + b; /* Create a DBC */ - } - w = ff_convert(w, 1); /* Convert ANSI/OEM to Unicode */ - if (!w) return FR_INVALID_NAME; /* Reject invalid code */ + w &= 0xFF; + + if ( IsDBCS1( w ) ) /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ + { + b = ( BYTE )p[si++]; /* Get 2nd byte */ + + if ( !IsDBCS2( b ) ) + { + return FR_INVALID_NAME; /* Reject invalid sequence */ + } + + w = ( w << 8 ) + b; /* Create a DBC */ + } + + w = ff_convert( w, 1 ); /* Convert ANSI/OEM to Unicode */ + + if ( !w ) + { + return FR_INVALID_NAME; /* Reject invalid code */ + } + #endif - if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) /* Reject illegal chars for LFN */ - return FR_INVALID_NAME; - lfn[di++] = w; /* Store the Unicode char */ - } - *path = &p[si]; /* Return pointer to the next segment */ - cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ + + if ( w < 0x80 && chk_chr( "\"*:<>\?|\x7F", w ) ) /* Reject illegal chars for LFN */ + { + return FR_INVALID_NAME; + } + + lfn[di++] = w; /* Store the Unicode char */ + } + + *path = &p[si]; /* Return pointer to the next segment */ + cf = ( w < ' ' ) ? NS_LAST : 0; /* Set last segment flag if end of path */ #if _FS_RPATH - if ((di == 1 && lfn[di-1] == '.') || /* Is this a dot entry? */ - (di == 2 && lfn[di-1] == '.' && lfn[di-2] == '.')) { - lfn[di] = 0; - for (i = 0; i < 11; i++) - dj->fn[i] = (i < di) ? '.' : ' '; - dj->fn[i] = cf | NS_DOT; /* This is a dot entry */ - return FR_OK; - } + + if ( ( di == 1 && lfn[di - 1] == '.' ) || /* Is this a dot entry? */ + ( di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.' ) ) + { + lfn[di] = 0; + + for ( i = 0; i < 11; i++ ) + { + dj->fn[i] = ( i < di ) ? '.' : ' '; + } + + dj->fn[i] = cf | NS_DOT; /* This is a dot entry */ + return FR_OK; + } + #endif - while (di) { /* Strip trailing spaces and dots */ - w = lfn[di-1]; - if (w != ' ' && w != '.') break; - di--; - } - if (!di) return FR_INVALID_NAME; /* Reject nul string */ - lfn[di] = 0; /* LFN is created */ + while ( di ) /* Strip trailing spaces and dots */ + { + w = lfn[di - 1]; - /* Create SFN in directory form */ - mem_set(dj->fn, ' ', 11); - for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; /* Strip leading spaces and dots */ - if (si) cf |= NS_LOSS | NS_LFN; - while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */ + if ( w != ' ' && w != '.' ) + { + break; + } - b = i = 0; ni = 8; - for (;;) { - w = lfn[si++]; /* Get an LFN char */ - if (!w) break; /* Break on end of the LFN */ - if (w == ' ' || (w == '.' && si != di)) { /* Remove spaces and dots */ - cf |= NS_LOSS | NS_LFN; continue; - } + di--; + } - if (i >= ni || si == di) { /* Extension or end of SFN */ - if (ni == 11) { /* Long extension */ - cf |= NS_LOSS | NS_LFN; break; - } - if (si != di) cf |= NS_LOSS | NS_LFN; /* Out of 8.3 format */ - if (si > di) break; /* No extension */ - si = di; i = 8; ni = 11; /* Enter extension section */ - b <<= 2; continue; - } + if ( !di ) + { + return FR_INVALID_NAME; /* Reject nul string */ + } - if (w >= 0x80) { /* Non ASCII char */ + lfn[di] = 0; /* LFN is created */ + + /* Create SFN in directory form */ + mem_set( dj->fn, ' ', 11 ); + + for ( si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++ ) ; /* Strip leading spaces and dots */ + + if ( si ) + { + cf |= NS_LOSS | NS_LFN; + } + + while ( di && lfn[di - 1] != '.' ) + { + di--; /* Find extension (di<=si: no extension) */ + } + + b = i = 0; ni = 8; + + for ( ;; ) + { + w = lfn[si++]; /* Get an LFN char */ + + if ( !w ) + { + break; /* Break on end of the LFN */ + } + + if ( w == ' ' || ( w == '.' && si != di ) ) /* Remove spaces and dots */ + { + cf |= NS_LOSS | NS_LFN; continue; + } + + if ( i >= ni || si == di ) /* Extension or end of SFN */ + { + if ( ni == 11 ) /* Long extension */ + { + cf |= NS_LOSS | NS_LFN; break; + } + + if ( si != di ) + { + cf |= NS_LOSS | NS_LFN; /* Out of 8.3 format */ + } + + if ( si > di ) + { + break; /* No extension */ + } + + si = di; i = 8; ni = 11; /* Enter extension section */ + b <<= 2; continue; + } + + if ( w >= 0x80 ) /* Non ASCII char */ + { #ifdef _EXCVT - w = ff_convert(w, 0); /* Unicode -> OEM code */ - if (w) w = excvt[w - 0x80]; /* Convert extended char to upper (SBCS) */ + w = ff_convert( w, 0 ); /* Unicode -> OEM code */ + + if ( w ) + { + w = excvt[w - 0x80]; /* Convert extended char to upper (SBCS) */ + } + #else - w = ff_convert(ff_wtoupper(w), 0); /* Upper converted Unicode -> OEM code */ + w = ff_convert( ff_wtoupper( w ), 0 ); /* Upper converted Unicode -> OEM code */ #endif - cf |= NS_LFN; /* Force create LFN entry */ - } + cf |= NS_LFN; /* Force create LFN entry */ + } - if (_DF1S && w >= 0x100) { /* Double byte char (always false on SBCS cfg) */ - if (i >= ni - 1) { - cf |= NS_LOSS | NS_LFN; i = ni; continue; - } - dj->fn[i++] = (BYTE)(w >> 8); - } else { /* Single byte char */ - if (!w || chk_chr("+,;=[]", w)) { /* Replace illegal chars for SFN */ - w = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */ - } else { - if (IsUpper(w)) { /* ASCII large capital */ - b |= 2; - } else { - if (IsLower(w)) { /* ASCII small capital */ - b |= 1; w -= 0x20; - } - } - } - } - dj->fn[i++] = (BYTE)w; - } + if ( _DF1S && w >= 0x100 ) /* Double byte char (always false on SBCS cfg) */ + { + if ( i >= ni - 1 ) + { + cf |= NS_LOSS | NS_LFN; i = ni; continue; + } - if (dj->fn[0] == 0xE5) dj->fn[0] = 0x05; /* If the first char collides with deleted mark, replace it with 0x05 */ + dj->fn[i++] = ( BYTE )( w >> 8 ); + } + else /* Single byte char */ + { + if ( !w || chk_chr( "+,;=[]", w ) ) /* Replace illegal chars for SFN */ + { + w = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */ + } + else + { + if ( IsUpper( w ) ) /* ASCII large capital */ + { + b |= 2; + } + else + { + if ( IsLower( w ) ) /* ASCII small capital */ + { + b |= 1; w -= 0x20; + } + } + } + } - if (ni == 8) b <<= 2; - if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) /* Create LFN entry when there are composite capitals */ - cf |= NS_LFN; - if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended char, NT flags are created */ - if ((b & 0x03) == 0x01) cf |= NS_EXT; /* NT flag (Extension has only small capital) */ - if ((b & 0x0C) == 0x04) cf |= NS_BODY; /* NT flag (Filename has only small capital) */ - } + dj->fn[i++] = ( BYTE )w; + } - dj->fn[NS] = cf; /* SFN is created */ + if ( dj->fn[0] == 0xE5 ) + { + dj->fn[0] = 0x05; /* If the first char collides with deleted mark, replace it with 0x05 */ + } - return FR_OK; + if ( ni == 8 ) + { + b <<= 2; + } + + if ( ( b & 0x0C ) == 0x0C || ( b & 0x03 ) == 0x03 ) /* Create LFN entry when there are composite capitals */ + { + cf |= NS_LFN; + } + + if ( !( cf & NS_LFN ) ) /* When LFN is in 8.3 format without extended char, NT flags are created */ + { + if ( ( b & 0x03 ) == 0x01 ) + { + cf |= NS_EXT; /* NT flag (Extension has only small capital) */ + } + + if ( ( b & 0x0C ) == 0x04 ) + { + cf |= NS_BODY; /* NT flag (Filename has only small capital) */ + } + } + + dj->fn[NS] = cf; /* SFN is created */ + + return FR_OK; -#else /* Non-LFN configuration */ - BYTE b, c, d, *sfn; - UINT ni, si, i; - const char *p; +#else /* Non-LFN configuration */ + BYTE b, c, d, *sfn; + UINT ni, si, i; + const char *p; - /* Create file name in directory form */ - sfn = dj->fn; - mem_set(sfn, ' ', 11); - si = i = b = 0; ni = 8; - p = *path; + /* Create file name in directory form */ + sfn = dj->fn; + mem_set( sfn, ' ', 11 ); + si = i = b = 0; ni = 8; + p = *path; #if _FS_RPATH - if (p[si] == '.') { /* Is this a dot entry? */ - for (;;) { - c = (BYTE)p[si++]; - if (c != '.' || si >= 3) break; - sfn[i++] = c; - } - if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME; - *path = &p[si]; /* Return pointer to the next segment */ - sfn[NS] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of path */ - return FR_OK; - } + + if ( p[si] == '.' ) /* Is this a dot entry? */ + { + for ( ;; ) + { + c = ( BYTE )p[si++]; + + if ( c != '.' || si >= 3 ) + { + break; + } + + sfn[i++] = c; + } + + if ( c != '/' && c != '\\' && c > ' ' ) + { + return FR_INVALID_NAME; + } + + *path = &p[si]; /* Return pointer to the next segment */ + sfn[NS] = ( c <= ' ' ) ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of path */ + return FR_OK; + } + #endif - for (;;) { - c = (BYTE)p[si++]; - if (c <= ' ' || c == '/' || c == '\\') break; /* Break on end of segment */ - if (c == '.' || i >= ni) { - if (ni != 8 || c != '.') return FR_INVALID_NAME; - i = 8; ni = 11; - b <<= 2; continue; - } - if (c >= 0x80) { /* Extended char? */ - b |= 3; /* Eliminate NT flag */ + + for ( ;; ) + { + c = ( BYTE )p[si++]; + + if ( c <= ' ' || c == '/' || c == '\\' ) + { + break; /* Break on end of segment */ + } + + if ( c == '.' || i >= ni ) + { + if ( ni != 8 || c != '.' ) + { + return FR_INVALID_NAME; + } + + i = 8; ni = 11; + b <<= 2; continue; + } + + if ( c >= 0x80 ) /* Extended char? */ + { + b |= 3; /* Eliminate NT flag */ #ifdef _EXCVT - c = excvt[c-0x80]; /* Upper conversion (SBCS) */ + c = excvt[c - 0x80]; /* Upper conversion (SBCS) */ #else -#if !_DF1S /* ASCII only cfg */ - return FR_INVALID_NAME; +#if !_DF1S /* ASCII only cfg */ + return FR_INVALID_NAME; #endif #endif - } - if (IsDBCS1(c)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ - d = (BYTE)p[si++]; /* Get 2nd byte */ - if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */ - return FR_INVALID_NAME; - sfn[i++] = c; - sfn[i++] = d; - } else { /* Single byte code */ - if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) /* Reject illegal chrs for SFN */ - return FR_INVALID_NAME; - if (IsUpper(c)) { /* ASCII large capital? */ - b |= 2; - } else { - if (IsLower(c)) { /* ASCII small capital? */ - b |= 1; c -= 0x20; - } - } - sfn[i++] = c; - } - } - *path = &p[si]; /* Return pointer to the next segment */ - c = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ + } - if (!i) return FR_INVALID_NAME; /* Reject nul string */ - if (sfn[0] == 0xE5) sfn[0] = 0x05; /* When first char collides with 0xE5, replace it with 0x05 */ + if ( IsDBCS1( c ) ) /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ + { + d = ( BYTE )p[si++]; /* Get 2nd byte */ - if (ni == 8) b <<= 2; - if ((b & 0x03) == 0x01) c |= NS_EXT; /* NT flag (Name extension has only small capital) */ - if ((b & 0x0C) == 0x04) c |= NS_BODY; /* NT flag (Name body has only small capital) */ + if ( !IsDBCS2( d ) || i >= ni - 1 ) /* Reject invalid DBC */ + { + return FR_INVALID_NAME; + } - sfn[NS] = c; /* Store NT flag, File name is created */ + sfn[i++] = c; + sfn[i++] = d; + } + else /* Single byte code */ + { + if ( chk_chr( "\"*+,:;<=>\?[]|\x7F", c ) ) /* Reject illegal chrs for SFN */ + { + return FR_INVALID_NAME; + } - return FR_OK; + if ( IsUpper( c ) ) /* ASCII large capital? */ + { + b |= 2; + } + else + { + if ( IsLower( c ) ) /* ASCII small capital? */ + { + b |= 1; c -= 0x20; + } + } + + sfn[i++] = c; + } + } + + *path = &p[si]; /* Return pointer to the next segment */ + c = ( c <= ' ' ) ? NS_LAST : 0; /* Set last segment flag if end of path */ + + if ( !i ) + { + return FR_INVALID_NAME; /* Reject nul string */ + } + + if ( sfn[0] == 0xE5 ) + { + sfn[0] = 0x05; /* When first char collides with 0xE5, replace it with 0x05 */ + } + + if ( ni == 8 ) + { + b <<= 2; + } + + if ( ( b & 0x03 ) == 0x01 ) + { + c |= NS_EXT; /* NT flag (Name extension has only small capital) */ + } + + if ( ( b & 0x0C ) == 0x04 ) + { + c |= NS_BODY; /* NT flag (Name body has only small capital) */ + } + + sfn[NS] = c; /* Store NT flag, File name is created */ + + return FR_OK; #endif } @@ -1594,78 +2307,151 @@ FRESULT create_name ( /*-----------------------------------------------------------------------*/ #if _FS_MINIMIZE <= 1 static -void get_fileinfo ( /* No return code */ - DIR *dj, /* Pointer to the directory object */ - FILINFO *fno /* Pointer to the file information to be filled */ +void get_fileinfo ( /* No return code */ + DIR *dj, /* Pointer to the directory object */ + FILINFO *fno /* Pointer to the file information to be filled */ ) { - UINT i; - BYTE nt, *dir; - TCHAR *p, c; + UINT i; + BYTE nt, *dir; + TCHAR *p, c; - p = fno->fname; - if (dj->sect) { - dir = dj->dir; - nt = dir[DIR_NTres]; /* NT flag */ - for (i = 0; i < 8; i++) { /* Copy name body */ - c = dir[i]; - if (c == ' ') break; - if (c == 0x05) c = (TCHAR)0xE5; - if (_USE_LFN && (nt & NS_BODY) && IsUpper(c)) c += 0x20; + p = fno->fname; + + if ( dj->sect ) + { + dir = dj->dir; + nt = dir[DIR_NTres]; /* NT flag */ + + for ( i = 0; i < 8; i++ ) /* Copy name body */ + { + c = dir[i]; + + if ( c == ' ' ) + { + break; + } + + if ( c == 0x05 ) + { + c = ( TCHAR )0xE5; + } + + if ( _USE_LFN && ( nt & NS_BODY ) && IsUpper( c ) ) + { + c += 0x20; + } + #if _LFN_UNICODE - if (IsDBCS1(c) && i < 7 && IsDBCS2(dir[i+1])) - c = (c << 8) | dir[++i]; - c = ff_convert(c, 1); - if (!c) c = '?'; + + if ( IsDBCS1( c ) && i < 7 && IsDBCS2( dir[i + 1] ) ) + { + c = ( c << 8 ) | dir[++i]; + } + + c = ff_convert( c, 1 ); + + if ( !c ) + { + c = '?'; + } + #endif - *p++ = c; - } - if (dir[8] != ' ') { /* Copy name extension */ - *p++ = '.'; - for (i = 8; i < 11; i++) { - c = dir[i]; - if (c == ' ') break; - if (_USE_LFN && (nt & NS_EXT) && IsUpper(c)) c += 0x20; + *p++ = c; + } + + if ( dir[8] != ' ' ) /* Copy name extension */ + { + *p++ = '.'; + + for ( i = 8; i < 11; i++ ) + { + c = dir[i]; + + if ( c == ' ' ) + { + break; + } + + if ( _USE_LFN && ( nt & NS_EXT ) && IsUpper( c ) ) + { + c += 0x20; + } + #if _LFN_UNICODE - if (IsDBCS1(c) && i < 10 && IsDBCS2(dir[i+1])) - c = (c << 8) | dir[++i]; - c = ff_convert(c, 1); - if (!c) c = '?'; + + if ( IsDBCS1( c ) && i < 10 && IsDBCS2( dir[i + 1] ) ) + { + c = ( c << 8 ) | dir[++i]; + } + + c = ff_convert( c, 1 ); + + if ( !c ) + { + c = '?'; + } + #endif - *p++ = c; - } - } - fno->fattrib = dir[DIR_Attr]; /* Attribute */ - fno->fsize = LD_DWORD(dir+DIR_FileSize); /* Size */ - fno->fdate = LD_WORD(dir+DIR_WrtDate); /* Date */ - fno->ftime = LD_WORD(dir+DIR_WrtTime); /* Time */ - fno->clust = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) - | LD_WORD(dir+DIR_FstClusLO); - } - *p = 0; /* Terminate SFN str by a \0 */ + *p++ = c; + } + } + + fno->fattrib = dir[DIR_Attr]; /* Attribute */ + fno->fsize = LD_DWORD( dir + DIR_FileSize ); /* Size */ + fno->fdate = LD_WORD( dir + DIR_WrtDate ); /* Date */ + fno->ftime = LD_WORD( dir + DIR_WrtTime ); /* Time */ + fno->clust = ( ( DWORD )LD_WORD( dir + DIR_FstClusHI ) << 16 ) + | LD_WORD( dir + DIR_FstClusLO ); + } + + *p = 0; /* Terminate SFN str by a \0 */ #if _USE_LFN - if (fno->lfname && fno->lfsize) { - TCHAR *tp = fno->lfname; - WCHAR w, *lfn; - i = 0; - if (dj->sect && dj->lfn_idx != 0xFFFF) {/* Get LFN if available */ - lfn = dj->lfn; - while ((w = *lfn++) != 0) { /* Get an LFN char */ + if ( fno->lfname && fno->lfsize ) + { + TCHAR *tp = fno->lfname; + WCHAR w, *lfn; + + i = 0; + + if ( dj->sect && dj->lfn_idx != 0xFFFF ) /* Get LFN if available */ + { + lfn = dj->lfn; + + while ( ( w = *lfn++ ) != 0 ) /* Get an LFN char */ + { #if !_LFN_UNICODE - w = ff_convert(w, 0); /* Unicode -> OEM conversion */ - if (!w) { i = 0; break; } /* Could not convert, no LFN */ - if (_DF1S && w >= 0x100) /* Put 1st byte if it is a DBC (always false on SBCS cfg) */ - tp[i++] = (TCHAR)(w >> 8); + w = ff_convert( w, 0 ); /* Unicode -> OEM conversion */ + + if ( !w ) + { + i = 0; /* Could not convert, no LFN */ + break; + } + + if ( _DF1S && w >= 0x100 ) /* Put 1st byte if it is a DBC (always false on SBCS cfg) */ + { + tp[i++] = ( TCHAR )( w >> 8 ); + } + #endif - if (i >= fno->lfsize - 1) { i = 0; break; } /* Buffer overflow, no LFN */ - tp[i++] = (TCHAR)w; - } - } - tp[i] = 0; /* Terminate the LFN str by a \0 */ - } + + if ( i >= fno->lfsize - 1 ) + { + i = 0; /* Buffer overflow, no LFN */ + break; + } + + tp[i++] = ( TCHAR )w; + } + } + + tp[i] = 0; /* Terminate the LFN str by a \0 */ + } + #endif } #endif /* _FS_MINIMIZE <= 1 */ @@ -1678,59 +2464,102 @@ void get_fileinfo ( /* No return code */ /*-----------------------------------------------------------------------*/ static -FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ - DIR *dj, /* Directory object to return last directory and found object */ - const TCHAR *path /* Full-path string to find a file or directory */ +FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ + DIR *dj, /* Directory object to return last directory and found object */ + const TCHAR *path /* Full-path string to find a file or directory */ ) { - FRESULT res; - BYTE *dir, ns; + FRESULT res; + BYTE *dir, ns; #if _FS_RPATH - if (*path == '/' || *path == '\\') { /* There is a heading separator */ - path++; dj->sclust = 0; /* Strip it and start from the root dir */ - } else { /* No heading separator */ - dj->sclust = dj->fs->cdir; /* Start from the current dir */ - } + + if ( *path == '/' || *path == '\\' ) /* There is a heading separator */ + { + path++; dj->sclust = 0; /* Strip it and start from the root dir */ + } + else /* No heading separator */ + { + dj->sclust = dj->fs->cdir; /* Start from the current dir */ + } + #else - if (*path == '/' || *path == '\\') /* Strip heading separator if exist */ - path++; - dj->sclust = 0; /* Start from the root dir */ + + if ( *path == '/' || *path == '\\' ) /* Strip heading separator if exist */ + { + path++; + } + + dj->sclust = 0; /* Start from the root dir */ #endif - if ((UINT)*path < ' ') { /* Nul path means the start directory itself */ - res = dir_sdi(dj, 0); - dj->dir = 0; + if ( ( UINT )*path < ' ' ) /* Nul path means the start directory itself */ + { + res = dir_sdi( dj, 0 ); + dj->dir = 0; - } else { /* Follow path */ - for (;;) { - res = create_name(dj, &path); /* Get a segment */ - if (res != FR_OK) break; - res = dir_find(dj); /* Find it */ - ns = *(dj->fn+NS); - if (res != FR_OK) { /* Failed to find the object */ - if (res != FR_NO_FILE) break; /* Abort if any hard error occured */ - /* Object not found */ - if (_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exit */ - dj->sclust = 0; dj->dir = 0; /* It is the root dir */ - res = FR_OK; - if (!(ns & NS_LAST)) continue; - } else { /* Could not find the object */ - if (!(ns & NS_LAST)) res = FR_NO_PATH; - } - break; - } - if (ns & NS_LAST) break; /* Last segment match. Function completed. */ - dir = dj->dir; /* There is next segment. Follow the sub directory */ - if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */ - res = FR_NO_PATH; break; - } - dj->sclust = LD_CLUST(dir); - } - } + } + else /* Follow path */ + { + for ( ;; ) + { + res = create_name( dj, &path ); /* Get a segment */ - return res; + if ( res != FR_OK ) + { + break; + } + + res = dir_find( dj ); /* Find it */ + ns = *( dj->fn + NS ); + + if ( res != FR_OK ) /* Failed to find the object */ + { + if ( res != FR_NO_FILE ) + { + break; /* Abort if any hard error occured */ + } + + /* Object not found */ + if ( _FS_RPATH && ( ns & NS_DOT ) ) /* If dot entry is not exit */ + { + dj->sclust = 0; dj->dir = 0; /* It is the root dir */ + res = FR_OK; + + if ( !( ns & NS_LAST ) ) + { + continue; + } + } + else /* Could not find the object */ + { + if ( !( ns & NS_LAST ) ) + { + res = FR_NO_PATH; + } + } + + break; + } + + if ( ns & NS_LAST ) + { + break; /* Last segment match. Function completed. */ + } + + dir = dj->dir; /* There is next segment. Follow the sub directory */ + + if ( !( dir[DIR_Attr] & AM_DIR ) ) /* Cannot follow because it is a file */ + { + res = FR_NO_PATH; break; + } + + dj->sclust = LD_CLUST( dir ); + } + } + + return res; } @@ -1741,22 +2570,33 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ /*-----------------------------------------------------------------------*/ static -BYTE check_fs ( /* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:Disk error */ - FATFS *fs, /* File system object */ - DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ +BYTE check_fs ( /* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:Disk error */ + FATFS *fs, /* File system object */ + DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ ) { - if (disk_read(fs->drv, fs->win, sect, 1) != RES_OK) /* Load boot record */ - return 3; - if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check record signature (always placed at offset 510 even if the sector size is >512) */ - return 2; + if ( disk_read( fs->drv, fs->win, sect, 1 ) != RES_OK ) /* Load boot record */ + { + return 3; + } - if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */ - return 0; - if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146) - return 0; + if ( LD_WORD( &fs->win[BS_55AA] ) != + 0xAA55 ) /* Check record signature (always placed at offset 510 even if the sector size is >512) */ + { + return 2; + } - return 1; + if ( ( LD_DWORD( &fs->win[BS_FilSysType] ) & 0xFFFFFF ) == 0x544146 ) /* Check "FAT" string */ + { + return 0; + } + + if ( ( LD_DWORD( &fs->win[BS_FilSysType32] ) & 0xFFFFFF ) == 0x544146 ) + { + return 0; + } + + return 1; } @@ -1767,161 +2607,268 @@ BYTE check_fs ( /* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:Disk e /*-----------------------------------------------------------------------*/ static -FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ - const TCHAR **path, /* Pointer to pointer to the path name (drive number) */ - FATFS **rfs, /* Pointer to pointer to the found file system object */ - BYTE chk_wp /* !=0: Check media write protection for write access */ +FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ + const TCHAR **path, /* Pointer to pointer to the path name (drive number) */ + FATFS **rfs, /* Pointer to pointer to the found file system object */ + BYTE chk_wp /* !=0: Check media write protection for write access */ ) { - BYTE fmt, b, *tbl; - UINT vol; - DSTATUS stat; - DWORD bsect, fasize, tsect, sysect, nclst, szbfat; - WORD nrsv; - const TCHAR *p = *path; - FATFS *fs; + BYTE fmt, b, *tbl; + UINT vol; + DSTATUS stat; + DWORD bsect, fasize, tsect, sysect, nclst, szbfat; + WORD nrsv; + const TCHAR *p = *path; + FATFS *fs; - /* Get logical drive number from the path name */ - vol = p[0] - '0'; /* Is there a drive number? */ - if (vol <= 9 && p[1] == ':') { /* Found a drive number, get and strip it */ - p += 2; *path = p; /* Return pointer to the path name */ - } else { /* No drive number is given */ + /* Get logical drive number from the path name */ + vol = p[0] - '0'; /* Is there a drive number? */ + + if ( vol <= 9 && p[1] == ':' ) /* Found a drive number, get and strip it */ + { + p += 2; *path = p; /* Return pointer to the path name */ + } + else /* No drive number is given */ + { #if _FS_RPATH - vol = CurrVol; /* Use current drive */ + vol = CurrVol; /* Use current drive */ #else - vol = 0; /* Use drive 0 */ + vol = 0; /* Use drive 0 */ #endif - } + } - /* Check if the logical drive is valid or not */ - if (vol >= _VOLUMES) /* Is the drive number valid? */ - return FR_INVALID_DRIVE; - *rfs = fs = FatFs[vol]; /* Return pointer to the corresponding file system object */ - if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */ + /* Check if the logical drive is valid or not */ + if ( vol >= _VOLUMES ) /* Is the drive number valid? */ + { + return FR_INVALID_DRIVE; + } - ENTER_FF(fs); /* Lock file system */ + *rfs = fs = FatFs[vol]; /* Return pointer to the corresponding file system object */ - if (fs->fs_type) { /* If the logical drive has been mounted */ - stat = disk_status(fs->drv); - if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized (has not been changed), */ + if ( !fs ) + { + return FR_NOT_ENABLED; /* Is the file system object available? */ + } + + ENTER_FF( fs ); /* Lock file system */ + + if ( fs->fs_type ) /* If the logical drive has been mounted */ + { + stat = disk_status( fs->drv ); + + if ( !( stat & STA_NOINIT ) ) /* and the physical drive is kept initialized (has not been changed), */ + { #if !_FS_READONLY - if (chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */ - return FR_WRITE_PROTECTED; + + if ( chk_wp && ( stat & STA_PROTECT ) ) /* Check write protection if needed */ + { + return FR_WRITE_PROTECTED; + } + #endif - return FR_OK; /* The file system object is valid */ - } - } + return FR_OK; /* The file system object is valid */ + } + } - /* The logical drive must be mounted. */ - /* Following code attempts to mount a volume. (analyze BPB and initialize the fs object) */ + /* The logical drive must be mounted. */ + /* Following code attempts to mount a volume. (analyze BPB and initialize the fs object) */ + + fs->fs_type = 0; /* Clear the file system object */ + fs->drv = ( BYTE )LD2PD( vol ); /* Bind the logical drive and a physical drive */ + stat = disk_initialize( fs->drv ); /* Initialize low level disk I/O layer */ + + if ( stat & STA_NOINIT ) /* Check if the initialization succeeded */ + { + return FR_NOT_READY; /* Failed to initialize due to no media or hard error */ + } + +#if _MAX_SS != 512 /* Get disk sector size (variable sector size cfg only) */ + + if ( disk_ioctl( fs->drv, GET_SECTOR_SIZE, &fs->ssize ) != RES_OK ) + { + return FR_DISK_ERR; + } - fs->fs_type = 0; /* Clear the file system object */ - fs->drv = (BYTE)LD2PD(vol); /* Bind the logical drive and a physical drive */ - stat = disk_initialize(fs->drv); /* Initialize low level disk I/O layer */ - if (stat & STA_NOINIT) /* Check if the initialization succeeded */ - return FR_NOT_READY; /* Failed to initialize due to no media or hard error */ -#if _MAX_SS != 512 /* Get disk sector size (variable sector size cfg only) */ - if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &fs->ssize) != RES_OK) - return FR_DISK_ERR; #endif #if !_FS_READONLY - if (chk_wp && (stat & STA_PROTECT)) /* Check disk write protection if needed */ - return FR_WRITE_PROTECTED; + + if ( chk_wp && ( stat & STA_PROTECT ) ) /* Check disk write protection if needed */ + { + return FR_WRITE_PROTECTED; + } + #endif - /* Search FAT partition on the drive. Supports only generic partitionings, FDISK and SFD. */ - fmt = check_fs(fs, bsect = 0); /* Check sector 0 if it is a VBR */ - if (fmt == 1) { /* Not an FAT-VBR, the disk may be partitioned */ - /* Check the partition listed in top of the partition table */ - tbl = &fs->win[MBR_Table + LD2PT(vol) * 16]; /* Partition table */ - if (tbl[4]) { /* Is the partition existing? */ - bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */ - fmt = check_fs(fs, bsect); /* Check the partition */ - } - } - if (fmt == 3) return FR_DISK_ERR; - if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */ + /* Search FAT partition on the drive. Supports only generic partitionings, FDISK and SFD. */ + fmt = check_fs( fs, bsect = 0 ); /* Check sector 0 if it is a VBR */ - /* Following code initializes the file system object */ + if ( fmt == 1 ) /* Not an FAT-VBR, the disk may be partitioned */ + { + /* Check the partition listed in top of the partition table */ + tbl = &fs->win[MBR_Table + LD2PT( vol ) * 16]; /* Partition table */ - if (LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs)) /* (BPB_BytsPerSec must be equal to the physical sector size) */ - return FR_NO_FILESYSTEM; + if ( tbl[4] ) /* Is the partition existing? */ + { + bsect = LD_DWORD( &tbl[8] ); /* Partition offset in LBA */ + fmt = check_fs( fs, bsect ); /* Check the partition */ + } + } - fasize = LD_WORD(fs->win+BPB_FATSz16); /* Number of sectors per FAT */ - if (!fasize) fasize = LD_DWORD(fs->win+BPB_FATSz32); - fs->fsize = fasize; + if ( fmt == 3 ) + { + return FR_DISK_ERR; + } - fs->n_fats = b = fs->win[BPB_NumFATs]; /* Number of FAT copies */ - if (b != 1 && b != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */ - fasize *= b; /* Number of sectors for FAT area */ + if ( fmt ) + { + return FR_NO_FILESYSTEM; /* No FAT volume is found */ + } - fs->csize = b = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */ - if (!b || (b & (b - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */ + /* Following code initializes the file system object */ - fs->n_rootdir = LD_WORD(fs->win+BPB_RootEntCnt); /* Number of root directory entries */ - if (fs->n_rootdir % (SS(fs) / 32)) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be sector aligned) */ + if ( LD_WORD( fs->win + BPB_BytsPerSec ) != SS( fs ) ) /* (BPB_BytsPerSec must be equal to the physical sector size) */ + { + return FR_NO_FILESYSTEM; + } - tsect = LD_WORD(fs->win+BPB_TotSec16); /* Number of sectors on the volume */ - if (!tsect) tsect = LD_DWORD(fs->win+BPB_TotSec32); + fasize = LD_WORD( fs->win + BPB_FATSz16 ); /* Number of sectors per FAT */ - nrsv = LD_WORD(fs->win+BPB_RsvdSecCnt); /* Number of reserved sectors */ - if (!nrsv) return FR_NO_FILESYSTEM; /* (BPB_RsvdSecCnt must not be 0) */ + if ( !fasize ) + { + fasize = LD_DWORD( fs->win + BPB_FATSz32 ); + } - /* Determine the FAT sub type */ - sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / 32); /* RSV+FAT+DIR */ - if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ - nclst = (tsect - sysect) / fs->csize; /* Number of clusters */ - if (!nclst) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ - fmt = FS_FAT12; - if (nclst >= MIN_FAT16) fmt = FS_FAT16; - if (nclst >= MIN_FAT32) fmt = FS_FAT32; + fs->fsize = fasize; - /* Boundaries and Limits */ - fs->n_fatent = nclst + 2; /* Number of FAT entries */ - fs->database = bsect + sysect; /* Data start sector */ - fs->fatbase = bsect + nrsv; /* FAT start sector */ - if (fmt == FS_FAT32) { - if (fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ - fs->dirbase = LD_DWORD(fs->win+BPB_RootClus); /* Root directory start cluster */ - szbfat = fs->n_fatent * 4; /* (Required FAT size) */ - } else { - if (!fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ - fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ - szbfat = (fmt == FS_FAT16) ? /* (Required FAT size) */ - fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); - } - if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) /* (FAT size must not be less than FAT sectors */ - return FR_NO_FILESYSTEM; + fs->n_fats = b = fs->win[BPB_NumFATs]; /* Number of FAT copies */ + + if ( b != 1 && b != 2 ) + { + return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */ + } + + fasize *= b; /* Number of sectors for FAT area */ + + fs->csize = b = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */ + + if ( !b || ( b & ( b - 1 ) ) ) + { + return FR_NO_FILESYSTEM; /* (Must be power of 2) */ + } + + fs->n_rootdir = LD_WORD( fs->win + BPB_RootEntCnt ); /* Number of root directory entries */ + + if ( fs->n_rootdir % ( SS( fs ) / 32 ) ) + { + return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be sector aligned) */ + } + + tsect = LD_WORD( fs->win + BPB_TotSec16 ); /* Number of sectors on the volume */ + + if ( !tsect ) + { + tsect = LD_DWORD( fs->win + BPB_TotSec32 ); + } + + nrsv = LD_WORD( fs->win + BPB_RsvdSecCnt ); /* Number of reserved sectors */ + + if ( !nrsv ) + { + return FR_NO_FILESYSTEM; /* (BPB_RsvdSecCnt must not be 0) */ + } + + /* Determine the FAT sub type */ + sysect = nrsv + fasize + fs->n_rootdir / ( SS( fs ) / 32 ); /* RSV+FAT+DIR */ + + if ( tsect < sysect ) + { + return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + } + + nclst = ( tsect - sysect ) / fs->csize; /* Number of clusters */ + + if ( !nclst ) + { + return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + } + + fmt = FS_FAT12; + + if ( nclst >= MIN_FAT16 ) + { + fmt = FS_FAT16; + } + + if ( nclst >= MIN_FAT32 ) + { + fmt = FS_FAT32; + } + + /* Boundaries and Limits */ + fs->n_fatent = nclst + 2; /* Number of FAT entries */ + fs->database = bsect + sysect; /* Data start sector */ + fs->fatbase = bsect + nrsv; /* FAT start sector */ + + if ( fmt == FS_FAT32 ) + { + if ( fs->n_rootdir ) + { + return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ + } + + fs->dirbase = LD_DWORD( fs->win + BPB_RootClus ); /* Root directory start cluster */ + szbfat = fs->n_fatent * 4; /* (Required FAT size) */ + } + else + { + if ( !fs->n_rootdir ) + { + return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ + } + + fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ + szbfat = ( fmt == FS_FAT16 ) ? /* (Required FAT size) */ + fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + ( fs->n_fatent & 1 ); + } + + if ( fs->fsize < ( szbfat + ( SS( fs ) - 1 ) ) / SS( fs ) ) /* (FAT size must not be less than FAT sectors */ + { + return FR_NO_FILESYSTEM; + } #if !_FS_READONLY - /* Initialize cluster allocation information */ - fs->free_clust = 0xFFFFFFFF; - fs->last_clust = 0; + /* Initialize cluster allocation information */ + fs->free_clust = 0xFFFFFFFF; + fs->last_clust = 0; + + /* Get fsinfo if available */ + if ( fmt == FS_FAT32 ) + { + fs->fsi_flag = 0; + fs->fsi_sector = bsect + LD_WORD( fs->win + BPB_FSInfo ); + + if ( disk_read( fs->drv, fs->win, fs->fsi_sector, 1 ) == RES_OK && + LD_WORD( fs->win + BS_55AA ) == 0xAA55 && + LD_DWORD( fs->win + FSI_LeadSig ) == 0x41615252 && + LD_DWORD( fs->win + FSI_StrucSig ) == 0x61417272 ) + { + fs->last_clust = LD_DWORD( fs->win + FSI_Nxt_Free ); + fs->free_clust = LD_DWORD( fs->win + FSI_Free_Count ); + } + } - /* Get fsinfo if available */ - if (fmt == FS_FAT32) { - fs->fsi_flag = 0; - fs->fsi_sector = bsect + LD_WORD(fs->win+BPB_FSInfo); - if (disk_read(fs->drv, fs->win, fs->fsi_sector, 1) == RES_OK && - LD_WORD(fs->win+BS_55AA) == 0xAA55 && - LD_DWORD(fs->win+FSI_LeadSig) == 0x41615252 && - LD_DWORD(fs->win+FSI_StrucSig) == 0x61417272) { - fs->last_clust = LD_DWORD(fs->win+FSI_Nxt_Free); - fs->free_clust = LD_DWORD(fs->win+FSI_Free_Count); - } - } #endif - fs->fs_type = fmt; /* FAT sub-type */ - fs->id = ++Fsid; /* File system mount ID */ - fs->winsect = 0; /* Invalidate sector cache */ - fs->wflag = 0; + fs->fs_type = fmt; /* FAT sub-type */ + fs->id = ++Fsid; /* File system mount ID */ + fs->winsect = 0; /* Invalidate sector cache */ + fs->wflag = 0; #if _FS_RPATH - fs->cdir = 0; /* Current directory (root dir) */ + fs->cdir = 0; /* Current directory (root dir) */ #endif -#if _FS_SHARE /* Clear file lock semaphores */ - clear_lock(fs); +#if _FS_SHARE /* Clear file lock semaphores */ + clear_lock( fs ); #endif - return FR_OK; + return FR_OK; } @@ -1932,21 +2879,25 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ /*-----------------------------------------------------------------------*/ static -FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */ - FATFS *fs, /* Pointer to the file system object */ - WORD id /* Member id of the target object to be checked */ +FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */ + FATFS *fs, /* Pointer to the file system object */ + WORD id /* Member id of the target object to be checked */ ) { -// printf("fs=%p fs->fs_type=%d fs->id=%d id=%d\n", fs, fs->fs_type, fs->id, id); - if (!fs || !fs->fs_type || fs->id != id) - return FR_INVALID_OBJECT; + // printf("fs=%p fs->fs_type=%d fs->id=%d id=%d\n", fs, fs->fs_type, fs->id, id); + if ( !fs || !fs->fs_type || fs->id != id ) + { + return FR_INVALID_OBJECT; + } - ENTER_FF(fs); /* Lock file system */ + ENTER_FF( fs ); /* Lock file system */ - if (disk_status(fs->drv) & STA_NOINIT) - return FR_NOT_READY; + if ( disk_status( fs->drv ) & STA_NOINIT ) + { + return FR_NOT_READY; + } - return FR_OK; + return FR_OK; } @@ -1965,36 +2916,52 @@ FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */ /*-----------------------------------------------------------------------*/ FRESULT f_mount ( - BYTE vol, /* Logical drive number to be mounted/unmounted */ - FATFS *fs /* Pointer to new file system object (NULL for unmount)*/ + BYTE vol, /* Logical drive number to be mounted/unmounted */ + FATFS *fs /* Pointer to new file system object (NULL for unmount)*/ ) { - FATFS *rfs; + FATFS *rfs; - if (vol >= _VOLUMES) /* Check if the drive number is valid */ - return FR_INVALID_DRIVE; - rfs = FatFs[vol]; /* Get current fs object */ + if ( vol >= _VOLUMES ) /* Check if the drive number is valid */ + { + return FR_INVALID_DRIVE; + } - if (rfs) { + rfs = FatFs[vol]; /* Get current fs object */ + + if ( rfs ) + { #if _FS_SHARE - clear_lock(rfs); + clear_lock( rfs ); #endif -#if _FS_REENTRANT /* Discard sync object of the current volume */ - if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR; -#endif - rfs->fs_type = 0; /* Clear old fs object */ - } +#if _FS_REENTRANT /* Discard sync object of the current volume */ - if (fs) { - fs->fs_type = 0; /* Clear new fs object */ -#if _FS_REENTRANT /* Create sync object for the new volume */ - if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR; -#endif - } - FatFs[vol] = fs; /* Register new fs object */ + if ( !ff_del_syncobj( rfs->sobj ) ) + { + return FR_INT_ERR; + } - return FR_OK; +#endif + rfs->fs_type = 0; /* Clear old fs object */ + } + + if ( fs ) + { + fs->fs_type = 0; /* Clear new fs object */ +#if _FS_REENTRANT /* Create sync object for the new volume */ + + if ( !ff_cre_syncobj( vol, &fs->sobj ) ) + { + return FR_INT_ERR; + } + +#endif + } + + FatFs[vol] = fs; /* Register new fs object */ + + return FR_OK; } @@ -2005,125 +2972,179 @@ FRESULT f_mount ( /*-----------------------------------------------------------------------*/ FRESULT f_open ( - FIL *fp, /* Pointer to the blank file object */ - const TCHAR *path, /* Pointer to the file name */ - BYTE mode /* Access mode and file open mode flags */ + FIL *fp, /* Pointer to the blank file object */ + const TCHAR *path, /* Pointer to the file name */ + BYTE mode /* Access mode and file open mode flags */ ) { - FRESULT res; - DIR dj; - BYTE *dir; - DEF_NAMEBUF; + FRESULT res; + DIR dj; + BYTE *dir; + DEF_NAMEBUF; - fp->fs = 0; /* Clear file object */ + fp->fs = 0; /* Clear file object */ #if !_FS_READONLY - mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW; - res = chk_mounted(&path, &dj.fs, (BYTE)(mode & ~FA_READ)); + mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW; + res = chk_mounted( &path, &dj.fs, ( BYTE )( mode & ~FA_READ ) ); #else - mode &= FA_READ; - res = chk_mounted(&path, &dj.fs, 0); + mode &= FA_READ; + res = chk_mounted( &path, &dj.fs, 0 ); #endif - INIT_BUF(dj); - if (res == FR_OK) - res = follow_path(&dj, path); /* Follow the file path */ - dir = dj.dir; + INIT_BUF( dj ); + + if ( res == FR_OK ) + { + res = follow_path( &dj, path ); /* Follow the file path */ + } + + dir = dj.dir; + +#if !_FS_READONLY /* R/W configuration */ + + if ( res == FR_OK ) + { + if ( !dir ) /* Current dir itself */ + { + res = FR_INVALID_NAME; + } -#if !_FS_READONLY /* R/W configuration */ - if (res == FR_OK) { - if (!dir) /* Current dir itself */ - res = FR_INVALID_NAME; #if _FS_SHARE - else - res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); + else + { + res = chk_lock( &dj, ( mode & ~FA_READ ) ? 1 : 0 ); + } + #endif - } - /* Create or Open a file */ - if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { - DWORD dw, cl; + } - if (res != FR_OK) { /* No file, create new */ - if (res == FR_NO_FILE) /* There is no file to open, create a new entry */ + /* Create or Open a file */ + if ( mode & ( FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW ) ) + { + DWORD dw, cl; + + if ( res != FR_OK ) /* No file, create new */ + { + if ( res == FR_NO_FILE ) /* There is no file to open, create a new entry */ #if _FS_SHARE - res = enq_lock(dj.fs) ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; + res = enq_lock( dj.fs ) ? dir_register( &dj ) : FR_TOO_MANY_OPEN_FILES; + #else - res = dir_register(&dj); + res = dir_register( &dj ); #endif - mode |= FA_CREATE_ALWAYS; /* File is created */ - dir = dj.dir; /* New entry */ - } - else { /* Any object is already existing */ - if (mode & FA_CREATE_NEW) { /* Cannot create new */ - res = FR_EXIST; - } else { - if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) /* Cannot overwrite it (R/O or DIR) */ - res = FR_DENIED; - } - } - if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */ - dw = get_fattime(); /* Created time */ - ST_DWORD(dir+DIR_CrtTime, dw); - dir[DIR_Attr] = 0; /* Reset attribute */ - ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */ - cl = LD_CLUST(dir); /* Get start cluster */ - ST_CLUST(dir, 0); /* cluster = 0 */ - dj.fs->wflag = 1; - if (cl) { /* Remove the cluster chain if exist */ - dw = dj.fs->winsect; - res = remove_chain(dj.fs, cl); - if (res == FR_OK) { - dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */ - res = move_window(dj.fs, dw); - } - } - } - } - else { /* Open an existing file */ - if (res == FR_OK) { /* Follow succeeded */ - if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */ - res = FR_NO_FILE; - } else { - if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */ - res = FR_DENIED; - } - } - } - if (res == FR_OK) { - if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */ - mode |= FA__WRITTEN; - fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */ - fp->dir_ptr = dir; + mode |= FA_CREATE_ALWAYS; /* File is created */ + dir = dj.dir; /* New entry */ + } + else /* Any object is already existing */ + { + if ( mode & FA_CREATE_NEW ) /* Cannot create new */ + { + res = FR_EXIST; + } + else + { + if ( dir[DIR_Attr] & ( AM_RDO | AM_DIR ) ) /* Cannot overwrite it (R/O or DIR) */ + { + res = FR_DENIED; + } + } + } + + if ( res == FR_OK && ( mode & FA_CREATE_ALWAYS ) ) /* Truncate it if overwrite mode */ + { + dw = get_fattime(); /* Created time */ + ST_DWORD( dir + DIR_CrtTime, dw ); + dir[DIR_Attr] = 0; /* Reset attribute */ + ST_DWORD( dir + DIR_FileSize, 0 ); /* size = 0 */ + cl = LD_CLUST( dir ); /* Get start cluster */ + ST_CLUST( dir, 0 ); /* cluster = 0 */ + dj.fs->wflag = 1; + + if ( cl ) /* Remove the cluster chain if exist */ + { + dw = dj.fs->winsect; + res = remove_chain( dj.fs, cl ); + + if ( res == FR_OK ) + { + dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */ + res = move_window( dj.fs, dw ); + } + } + } + } + else /* Open an existing file */ + { + if ( res == FR_OK ) /* Follow succeeded */ + { + if ( dir[DIR_Attr] & AM_DIR ) /* It is a directory */ + { + res = FR_NO_FILE; + } + else + { + if ( ( mode & FA_WRITE ) && ( dir[DIR_Attr] & AM_RDO ) ) /* R/O violation */ + { + res = FR_DENIED; + } + } + } + } + + if ( res == FR_OK ) + { + if ( mode & FA_CREATE_ALWAYS ) /* Set file change flag if created or overwritten */ + { + mode |= FA__WRITTEN; + } + + fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */ + fp->dir_ptr = dir; #if _FS_SHARE - fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); - if (!fp->lockid) res = FR_INT_ERR; -#endif - } + fp->lockid = inc_lock( &dj, ( mode & ~FA_READ ) ? 1 : 0 ); -#else /* R/O configuration */ - if (res == FR_OK) { /* Follow succeeded */ - if (!dir) { /* Current dir itself */ - res = FR_INVALID_NAME; - } else { - if (dir[DIR_Attr] & AM_DIR) /* It is a directory */ - res = FR_NO_FILE; - } - } -#endif - FREE_BUF(); + if ( !fp->lockid ) + { + res = FR_INT_ERR; + } - if (res == FR_OK) { - fp->flag = mode; /* File access mode */ - fp->org_clust = LD_CLUST(dir); /* File start cluster */ - fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */ - fp->fptr = 0; /* File pointer */ - fp->dsect = 0; +#endif + } + +#else /* R/O configuration */ + + if ( res == FR_OK ) /* Follow succeeded */ + { + if ( !dir ) /* Current dir itself */ + { + res = FR_INVALID_NAME; + } + else + { + if ( dir[DIR_Attr] & AM_DIR ) /* It is a directory */ + { + res = FR_NO_FILE; + } + } + } + +#endif + FREE_BUF(); + + if ( res == FR_OK ) + { + fp->flag = mode; /* File access mode */ + fp->org_clust = LD_CLUST( dir ); /* File start cluster */ + fp->fsize = LD_DWORD( dir + DIR_FileSize ); /* File size */ + fp->fptr = 0; /* File pointer */ + fp->dsect = 0; #if _USE_FASTSEEK - fp->cltbl = 0; /* No cluster link map table */ + fp->cltbl = 0; /* No cluster link map table */ #endif - fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */ - } + fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */ + } - LEAVE_FF(dj.fs, res); + LEAVE_FF( dj.fs, res ); } @@ -2134,110 +3155,195 @@ FRESULT f_open ( /*-----------------------------------------------------------------------*/ FRESULT f_read ( - FIL *fp, /* Pointer to the file object */ - void *buff, /* Pointer to data buffer */ - UINT btr, /* Number of bytes to read */ - UINT *br /* Pointer to number of bytes read */ + FIL *fp, /* Pointer to the file object */ + void *buff, /* Pointer to data buffer */ + UINT btr, /* Number of bytes to read */ + UINT *br /* Pointer to number of bytes read */ ) { - FRESULT res; - DWORD clst, sect, remain; - UINT rcnt, cc; - BYTE csect, *rbuff = buff; + FRESULT res; + DWORD clst, sect, remain; + UINT rcnt, cc; + BYTE csect, *rbuff = buff; - if(btr>512 && !ff_sd_offload) printf("WARNING: read >512 bytes but offloading is inactive!!\n"); + if ( btr > 512 && !ff_sd_offload ) + { + printf( "WARNING: read >512 bytes but offloading is inactive!!\n" ); + } - *br = 0; /* Initialize byte counter */ + *br = 0; /* Initialize byte counter */ - res = validate(fp->fs, fp->id); /* Check validity of the object */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->flag & FA__ERROR) /* Check abort flag */ - LEAVE_FF(fp->fs, FR_INT_ERR); - if (!(fp->flag & FA_READ)) /* Check access mode */ - LEAVE_FF(fp->fs, FR_DENIED); - remain = fp->fsize - fp->fptr; - if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ + res = validate( fp->fs, fp->id ); /* Check validity of the object */ - for ( ; btr; /* Repeat until all data transferred */ - rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) { - if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ - if (!csect) { /* On the cluster boundary? */ - clst = (fp->fptr == 0) ? /* On the top of the file? */ - fp->org_clust : get_fat(fp->fs, fp->curr_clust); - if (clst <= 1) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->curr_clust = clst; /* Update current cluster */ - } - sect = clust2sect(fp->fs, fp->curr_clust); /* Get current sector */ - if (!sect) ABORT(fp->fs, FR_INT_ERR); - sect += csect; - cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */ - if (cc) { /* Read maximum contiguous sectors directly */ - if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ - cc = fp->fs->csize - csect; -/* XXX OFFLOAD GOES HERE */ - if (ff_sd_offload) { - sd_offload = 1; - } - if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - sd_offload = 0; -#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ + if ( res != FR_OK ) + { + LEAVE_FF( fp->fs, res ); + } + + if ( fp->flag & FA__ERROR ) /* Check abort flag */ + { + LEAVE_FF( fp->fs, FR_INT_ERR ); + } + + if ( !( fp->flag & FA_READ ) ) /* Check access mode */ + { + LEAVE_FF( fp->fs, FR_DENIED ); + } + + remain = fp->fsize - fp->fptr; + + if ( btr > remain ) + { + btr = ( UINT )remain; /* Truncate btr by remaining bytes */ + } + + for ( ; btr; /* Repeat until all data transferred */ + rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt ) + { + if ( ( fp->fptr % SS( fp->fs ) ) == 0 ) /* On the sector boundary? */ + { + csect = ( BYTE )( fp->fptr / SS( fp->fs ) & ( fp->fs->csize - 1 ) ); /* Sector offset in the cluster */ + + if ( !csect ) /* On the cluster boundary? */ + { + clst = ( fp->fptr == 0 ) ? /* On the top of the file? */ + fp->org_clust : get_fat( fp->fs, fp->curr_clust ); + + if ( clst <= 1 ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + if ( clst == 0xFFFFFFFF ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->curr_clust = clst; /* Update current cluster */ + } + + sect = clust2sect( fp->fs, fp->curr_clust ); /* Get current sector */ + + if ( !sect ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + sect += csect; + cc = btr / SS( fp->fs ); /* When remaining bytes >= sector size, */ + + if ( cc ) /* Read maximum contiguous sectors directly */ + { + if ( csect + cc > fp->fs->csize ) /* Clip at cluster boundary */ + { + cc = fp->fs->csize - csect; + } + + /* XXX OFFLOAD GOES HERE */ + if ( ff_sd_offload ) + { + sd_offload = 1; + } + + if ( disk_read( fp->fs->drv, rbuff, sect, ( BYTE )cc ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + sd_offload = 0; +#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ #if _FS_TINY - if (fp->fs->wflag && fp->fs->winsect - sect < cc) - mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs)); + + if ( fp->fs->wflag && fp->fs->winsect - sect < cc ) + { + mem_cpy( rbuff + ( ( fp->fs->winsect - sect ) * SS( fp->fs ) ), fp->fs->win, SS( fp->fs ) ); + } + #else - if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc){ - mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); uart_putc('Y');} + + if ( ( fp->flag & FA__DIRTY ) && fp->dsect - sect < cc ) + { + mem_cpy( rbuff + ( ( fp->dsect - sect ) * SS( fp->fs ) ), fp->buf, SS( fp->fs ) ); uart_putc( 'Y' ); + } + #endif #endif - rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ - continue; - } + rcnt = SS( fp->fs ) * cc; /* Number of bytes transferred */ + continue; + } + #if !_FS_TINY #if !_FS_READONLY - if (fp->flag & FA__DIRTY) { /* Write sector I/O buffer if needed */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } + + if ( fp->flag & FA__DIRTY ) /* Write sector I/O buffer if needed */ + { + if ( disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->flag &= ~FA__DIRTY; + } + #endif - if (fp->dsect != sect) { /* Fill sector buffer with file data */ - if(!ff_sd_offload) { - if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - } - } + + if ( fp->dsect != sect ) /* Fill sector buffer with file data */ + { + if ( !ff_sd_offload ) + { + if ( disk_read( fp->fs->drv, fp->buf, sect, 1 ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + } + } + #endif - fp->dsect = sect; - } - rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */ - if (rcnt > btr) rcnt = btr; - if(!ff_sd_offload) { + fp->dsect = sect; + } + + rcnt = SS( fp->fs ) - ( fp->fptr % SS( fp->fs ) ); /* Get partial sector data from sector buffer */ + + if ( rcnt > btr ) + { + rcnt = btr; + } + + if ( !ff_sd_offload ) + { #if _FS_TINY - if (move_window(fp->fs, fp->dsect)) /* Move sector window */ - ABORT(fp->fs, FR_DISK_ERR); - mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ + + if ( move_window( fp->fs, fp->dsect ) ) /* Move sector window */ + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + mem_cpy( rbuff, &fp->fs->win[fp->fptr % SS( fp->fs )], rcnt ); /* Pick partial sector */ #else - mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ - } else { - sd_offload_partial_start = fp->fptr % SS(fp->fs); - sd_offload_partial_end = sd_offload_partial_start + rcnt; -// printf("partial dma. sect=%08lx start=%d end=%d\n", fp->dsect, sd_offload_partial_start, sd_offload_partial_end); - /* set start + end */ - sd_offload = 1; - sd_offload_partial = 1; - if(disk_read(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) { - sd_offload = 0; - ABORT(fp->fs, FR_DISK_ERR); - } - sd_offload = 0; + mem_cpy( rbuff, &fp->buf[fp->fptr % SS( fp->fs )], rcnt ); /* Pick partial sector */ + } + else + { + sd_offload_partial_start = fp->fptr % SS( fp->fs ); + sd_offload_partial_end = sd_offload_partial_start + rcnt; + // printf("partial dma. sect=%08lx start=%d end=%d\n", fp->dsect, sd_offload_partial_start, sd_offload_partial_end); + /* set start + end */ + sd_offload = 1; + sd_offload_partial = 1; + + if ( disk_read( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK ) + { + sd_offload = 0; + ABORT( fp->fs, FR_DISK_ERR ); + } + + sd_offload = 0; #endif - } - } - ff_sd_offload = 0; - LEAVE_FF(fp->fs, FR_OK); + } + } + + ff_sd_offload = 0; + LEAVE_FF( fp->fs, FR_OK ); } @@ -2249,110 +3355,205 @@ FRESULT f_read ( /*-----------------------------------------------------------------------*/ FRESULT f_write ( - FIL *fp, /* Pointer to the file object */ - const void *buff, /* Pointer to the data to be written */ - UINT btw, /* Number of bytes to write */ - UINT *bw /* Pointer to number of bytes written */ + FIL *fp, /* Pointer to the file object */ + const void *buff, /* Pointer to the data to be written */ + UINT btw, /* Number of bytes to write */ + UINT *bw /* Pointer to number of bytes written */ ) { - FRESULT res; - DWORD clst, sect; - UINT wcnt, cc; - const BYTE *wbuff = buff; - BYTE csect; + FRESULT res; + DWORD clst, sect; + UINT wcnt, cc; + const BYTE *wbuff = buff; + BYTE csect; - *bw = 0; /* Initialize byte counter */ + *bw = 0; /* Initialize byte counter */ - res = validate(fp->fs, fp->id); /* Check validity of the object */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->flag & FA__ERROR) /* Check abort flag */ - LEAVE_FF(fp->fs, FR_INT_ERR); - if (!(fp->flag & FA_WRITE)) /* Check access mode */ - LEAVE_FF(fp->fs, FR_DENIED); - if (fp->fsize + btw < fp->fsize) btw = 0; /* File size cannot reach 4GB */ + res = validate( fp->fs, fp->id ); /* Check validity of the object */ + + if ( res != FR_OK ) + { + LEAVE_FF( fp->fs, res ); + } + + if ( fp->flag & FA__ERROR ) /* Check abort flag */ + { + LEAVE_FF( fp->fs, FR_INT_ERR ); + } + + if ( !( fp->flag & FA_WRITE ) ) /* Check access mode */ + { + LEAVE_FF( fp->fs, FR_DENIED ); + } + + if ( fp->fsize + btw < fp->fsize ) + { + btw = 0; /* File size cannot reach 4GB */ + } + + for ( ; btw; /* Repeat until all data transferred */ + wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt ) + { + if ( ( fp->fptr % SS( fp->fs ) ) == 0 ) /* On the sector boundary? */ + { + csect = ( BYTE )( fp->fptr / SS( fp->fs ) & ( fp->fs->csize - 1 ) ); /* Sector offset in the cluster */ + + if ( !csect ) /* On the cluster boundary? */ + { + if ( fp->fptr == 0 ) /* On the top of the file? */ + { + clst = fp->org_clust; /* Follow from the origin */ + + if ( clst == 0 ) /* When there is no cluster chain, */ + { + fp->org_clust = clst = create_chain( fp->fs, 0 ); /* Create a new cluster chain */ + } + } + else /* Middle or end of the file */ + { + clst = create_chain( fp->fs, fp->curr_clust ); /* Follow or stretch cluster chain */ + } + + if ( clst == 0 ) + { + break; /* Could not allocate a new cluster (disk full) */ + } + + if ( clst == 1 ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + if ( clst == 0xFFFFFFFF ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->curr_clust = clst; /* Update current cluster */ + } - for ( ; btw; /* Repeat until all data transferred */ - wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) { - if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ - if (!csect) { /* On the cluster boundary? */ - if (fp->fptr == 0) { /* On the top of the file? */ - clst = fp->org_clust; /* Follow from the origin */ - if (clst == 0) /* When there is no cluster chain, */ - fp->org_clust = clst = create_chain(fp->fs, 0); /* Create a new cluster chain */ - } else { /* Middle or end of the file */ - clst = create_chain(fp->fs, fp->curr_clust); /* Follow or stretch cluster chain */ - } - if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ - if (clst == 1) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->curr_clust = clst; /* Update current cluster */ - } #if _FS_TINY - if (fp->fs->winsect == fp->dsect && move_window(fp->fs, 0)) /* Write back data buffer prior to following direct transfer */ - ABORT(fp->fs, FR_DISK_ERR); -#else - if (fp->flag & FA__DIRTY) { /* Write back data buffer prior to following direct transfer */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } -#endif - sect = clust2sect(fp->fs, fp->curr_clust); /* Get current sector */ - if (!sect) ABORT(fp->fs, FR_INT_ERR); - sect += csect; - cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */ - if (cc) { /* Write maximum contiguous sectors directly */ - if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ - cc = fp->fs->csize - csect; - if (disk_write(fp->fs->drv, wbuff, sect, (BYTE)cc) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); -#if _FS_TINY - if (fp->fs->winsect - sect < cc) { /* Refill sector cache if it gets dirty by the direct write */ - mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs)); - fp->fs->wflag = 0; - } -#else - if (fp->dsect - sect < cc) { /* Refill sector cache if it gets dirty by the direct write */ - mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)), SS(fp->fs)); - fp->flag &= ~FA__DIRTY; - } -#endif - wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ - continue; - } -#if _FS_TINY - if (fp->fptr >= fp->fsize) { /* Avoid silly buffer filling at growing edge */ - if (move_window(fp->fs, 0)) ABORT(fp->fs, FR_DISK_ERR); - fp->fs->winsect = sect; - } -#else - if (fp->dsect != sect) { /* Fill sector buffer with file data */ - if (fp->fptr < fp->fsize && - disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - } -#endif - fp->dsect = sect; - } - wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */ - if (wcnt > btw) wcnt = btw; -#if _FS_TINY - if (move_window(fp->fs, fp->dsect)) /* Move sector window */ - ABORT(fp->fs, FR_DISK_ERR); - mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */ - fp->fs->wflag = 1; -#else - mem_cpy(&fp->buf[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */ - fp->flag |= FA__DIRTY; -#endif - } - if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; /* Update file size if needed */ - fp->flag |= FA__WRITTEN; /* Set file change flag */ + if ( fp->fs->winsect == fp->dsect + && move_window( fp->fs, 0 ) ) /* Write back data buffer prior to following direct transfer */ + { + ABORT( fp->fs, FR_DISK_ERR ); + } - LEAVE_FF(fp->fs, FR_OK); +#else + + if ( fp->flag & FA__DIRTY ) /* Write back data buffer prior to following direct transfer */ + { + if ( disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->flag &= ~FA__DIRTY; + } + +#endif + sect = clust2sect( fp->fs, fp->curr_clust ); /* Get current sector */ + + if ( !sect ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + sect += csect; + cc = btw / SS( fp->fs ); /* When remaining bytes >= sector size, */ + + if ( cc ) /* Write maximum contiguous sectors directly */ + { + if ( csect + cc > fp->fs->csize ) /* Clip at cluster boundary */ + { + cc = fp->fs->csize - csect; + } + + if ( disk_write( fp->fs->drv, wbuff, sect, ( BYTE )cc ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + +#if _FS_TINY + + if ( fp->fs->winsect - sect < cc ) /* Refill sector cache if it gets dirty by the direct write */ + { + mem_cpy( fp->fs->win, wbuff + ( ( fp->fs->winsect - sect ) * SS( fp->fs ) ), SS( fp->fs ) ); + fp->fs->wflag = 0; + } + +#else + + if ( fp->dsect - sect < cc ) /* Refill sector cache if it gets dirty by the direct write */ + { + mem_cpy( fp->buf, wbuff + ( ( fp->dsect - sect ) * SS( fp->fs ) ), SS( fp->fs ) ); + fp->flag &= ~FA__DIRTY; + } + +#endif + wcnt = SS( fp->fs ) * cc; /* Number of bytes transferred */ + continue; + } + +#if _FS_TINY + + if ( fp->fptr >= fp->fsize ) /* Avoid silly buffer filling at growing edge */ + { + if ( move_window( fp->fs, 0 ) ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->fs->winsect = sect; + } + +#else + + if ( fp->dsect != sect ) /* Fill sector buffer with file data */ + { + if ( fp->fptr < fp->fsize && + disk_read( fp->fs->drv, fp->buf, sect, 1 ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + } + +#endif + fp->dsect = sect; + } + + wcnt = SS( fp->fs ) - ( fp->fptr % SS( fp->fs ) ); /* Put partial sector into file I/O buffer */ + + if ( wcnt > btw ) + { + wcnt = btw; + } + +#if _FS_TINY + + if ( move_window( fp->fs, fp->dsect ) ) /* Move sector window */ + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + mem_cpy( &fp->fs->win[fp->fptr % SS( fp->fs )], wbuff, wcnt ); /* Fit partial sector */ + fp->fs->wflag = 1; +#else + mem_cpy( &fp->buf[fp->fptr % SS( fp->fs )], wbuff, wcnt ); /* Fit partial sector */ + fp->flag |= FA__DIRTY; +#endif + } + + if ( fp->fptr > fp->fsize ) + { + fp->fsize = fp->fptr; /* Update file size if needed */ + } + + fp->flag |= FA__WRITTEN; /* Set file change flag */ + + LEAVE_FF( fp->fs, FR_OK ); } @@ -2363,41 +3564,52 @@ FRESULT f_write ( /*-----------------------------------------------------------------------*/ FRESULT f_sync ( - FIL *fp /* Pointer to the file object */ + FIL *fp /* Pointer to the file object */ ) { - FRESULT res; - DWORD tim; - BYTE *dir; + FRESULT res; + DWORD tim; + BYTE *dir; - res = validate(fp->fs, fp->id); /* Check validity of the object */ - if (res == FR_OK) { - if (fp->flag & FA__WRITTEN) { /* Has the file been written? */ -#if !_FS_TINY /* Write-back dirty buffer */ - if (fp->flag & FA__DIRTY) { - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - LEAVE_FF(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } + res = validate( fp->fs, fp->id ); /* Check validity of the object */ + + if ( res == FR_OK ) + { + if ( fp->flag & FA__WRITTEN ) /* Has the file been written? */ + { +#if !_FS_TINY /* Write-back dirty buffer */ + + if ( fp->flag & FA__DIRTY ) + { + if ( disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK ) + { + LEAVE_FF( fp->fs, FR_DISK_ERR ); + } + + fp->flag &= ~FA__DIRTY; + } + #endif - /* Update the directory entry */ - res = move_window(fp->fs, fp->dir_sect); - if (res == FR_OK) { - dir = fp->dir_ptr; - dir[DIR_Attr] |= AM_ARC; /* Set archive bit */ - ST_DWORD(dir+DIR_FileSize, fp->fsize); /* Update file size */ - ST_CLUST(dir, fp->org_clust); /* Update start cluster */ - tim = get_fattime(); /* Update updated time */ - ST_DWORD(dir+DIR_WrtTime, tim); - fp->flag &= ~FA__WRITTEN; - fp->fs->wflag = 1; - res = sync(fp->fs); - } - } - } + /* Update the directory entry */ + res = move_window( fp->fs, fp->dir_sect ); - LEAVE_FF(fp->fs, res); + if ( res == FR_OK ) + { + dir = fp->dir_ptr; + dir[DIR_Attr] |= AM_ARC; /* Set archive bit */ + ST_DWORD( dir + DIR_FileSize, fp->fsize ); /* Update file size */ + ST_CLUST( dir, fp->org_clust ); /* Update start cluster */ + tim = get_fattime(); /* Update updated time */ + ST_DWORD( dir + DIR_WrtTime, tim ); + fp->flag &= ~FA__WRITTEN; + fp->fs->wflag = 1; + res = sync( fp->fs ); + } + } + } + + LEAVE_FF( fp->fs, res ); } #endif /* !_FS_READONLY */ @@ -2410,34 +3622,50 @@ FRESULT f_sync ( /*-----------------------------------------------------------------------*/ FRESULT f_close ( - FIL *fp /* Pointer to the file object to be closed */ + FIL *fp /* Pointer to the file object to be closed */ ) { - FRESULT res; + FRESULT res; #if _FS_READONLY - FATFS *fs = fp->fs; - res = validate(fs, fp->id); - if (res == FR_OK) fp->fs = 0; /* Discard file object */ - LEAVE_FF(fs, res); + FATFS *fs = fp->fs; + res = validate( fs, fp->id ); + + if ( res == FR_OK ) + { + fp->fs = 0; /* Discard file object */ + } + + LEAVE_FF( fs, res ); #else - res = f_sync(fp); /* Flush cached data */ + res = f_sync( fp ); /* Flush cached data */ #if _FS_SHARE - if (res == FR_OK) { /* Decrement open counter */ + + if ( res == FR_OK ) /* Decrement open counter */ + { #if _FS_REENTRANT - res = validate(fp->fs, fp->id); - if (res == FR_OK) { - res = dec_lock(fp->lockid); - unlock_fs(fp->fs, FR_OK); - } + res = validate( fp->fs, fp->id ); + + if ( res == FR_OK ) + { + res = dec_lock( fp->lockid ); + unlock_fs( fp->fs, FR_OK ); + } + #else - res = dec_lock(fp->lockid); + res = dec_lock( fp->lockid ); #endif - } + } + #endif - if (res == FR_OK) fp->fs = 0; /* Discard file object */ - return res; + + if ( res == FR_OK ) + { + fp->fs = 0; /* Discard file object */ + } + + return res; #endif } @@ -2451,117 +3679,196 @@ FRESULT f_close ( #if _FS_RPATH >= 1 FRESULT f_chdrive ( - BYTE drv /* Drive number */ + BYTE drv /* Drive number */ ) { - if (drv >= _VOLUMES) return FR_INVALID_DRIVE; + if ( drv >= _VOLUMES ) + { + return FR_INVALID_DRIVE; + } - CurrVol = drv; + CurrVol = drv; - return FR_OK; + return FR_OK; } FRESULT f_chdir ( - const TCHAR *path /* Pointer to the directory path */ + const TCHAR *path /* Pointer to the directory path */ ) { - FRESULT res; - DIR dj; - DEF_NAMEBUF; + FRESULT res; + DIR dj; + DEF_NAMEBUF; - res = chk_mounted(&path, &dj.fs, 0); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the path */ - FREE_BUF(); - if (res == FR_OK) { /* Follow completed */ - if (!dj.dir) { - dj.fs->cdir = dj.sclust; /* Start directory itself */ - } else { - if (dj.dir[DIR_Attr] & AM_DIR) /* Reached to the directory */ - dj.fs->cdir = LD_CLUST(dj.dir); - else - res = FR_NO_PATH; /* Reached but a file */ - } - } - if (res == FR_NO_FILE) res = FR_NO_PATH; - } + res = chk_mounted( &path, &dj.fs, 0 ); - LEAVE_FF(dj.fs, res); + if ( res == FR_OK ) + { + INIT_BUF( dj ); + res = follow_path( &dj, path ); /* Follow the path */ + FREE_BUF(); + + if ( res == FR_OK ) /* Follow completed */ + { + if ( !dj.dir ) + { + dj.fs->cdir = dj.sclust; /* Start directory itself */ + } + else + { + if ( dj.dir[DIR_Attr] & AM_DIR ) /* Reached to the directory */ + { + dj.fs->cdir = LD_CLUST( dj.dir ); + } + else + { + res = FR_NO_PATH; /* Reached but a file */ + } + } + } + + if ( res == FR_NO_FILE ) + { + res = FR_NO_PATH; + } + } + + LEAVE_FF( dj.fs, res ); } #if _FS_RPATH >= 2 FRESULT f_getcwd ( - TCHAR *path, /* Pointer to the directory path */ - UINT sz_path /* Size of path */ + TCHAR *path, /* Pointer to the directory path */ + UINT sz_path /* Size of path */ ) { - FRESULT res; - DIR dj; - UINT i, n; - DWORD ccl; - TCHAR *tp; - FILINFO fno; - DEF_NAMEBUF; + FRESULT res; + DIR dj; + UINT i, n; + DWORD ccl; + TCHAR *tp; + FILINFO fno; + DEF_NAMEBUF; - *path = 0; - res = chk_mounted((const TCHAR**)&path, &dj.fs, 0); /* Get current volume */ - if (res == FR_OK) { - INIT_BUF(dj); - i = sz_path; /* Bottom of buffer (dir stack base) */ - dj.sclust = dj.fs->cdir; /* Start to follow upper dir from current dir */ - while ((ccl = dj.sclust) != 0) { /* Repeat while current dir is a sub-dir */ - res = dir_sdi(&dj, 1); /* Get parent dir */ - if (res != FR_OK) break; - res = dir_read(&dj); - if (res != FR_OK) break; - dj.sclust = LD_CLUST(dj.dir); /* Goto parent dir */ - res = dir_sdi(&dj, 0); - if (res != FR_OK) break; - do { /* Find the entry links to the child dir */ - res = dir_read(&dj); - if (res != FR_OK) break; - if (ccl == LD_CLUST(dj.dir)) break; /* Found the entry */ - res = dir_next(&dj, 0); - } while (res == FR_OK); - if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ - if (res != FR_OK) break; + *path = 0; + res = chk_mounted( ( const TCHAR ** )&path, &dj.fs, 0 ); /* Get current volume */ + + if ( res == FR_OK ) + { + INIT_BUF( dj ); + i = sz_path; /* Bottom of buffer (dir stack base) */ + dj.sclust = dj.fs->cdir; /* Start to follow upper dir from current dir */ + + while ( ( ccl = dj.sclust ) != 0 ) /* Repeat while current dir is a sub-dir */ + { + res = dir_sdi( &dj, 1 ); /* Get parent dir */ + + if ( res != FR_OK ) + { + break; + } + + res = dir_read( &dj ); + + if ( res != FR_OK ) + { + break; + } + + dj.sclust = LD_CLUST( dj.dir ); /* Goto parent dir */ + res = dir_sdi( &dj, 0 ); + + if ( res != FR_OK ) + { + break; + } + + do /* Find the entry links to the child dir */ + { + res = dir_read( &dj ); + + if ( res != FR_OK ) + { + break; + } + + if ( ccl == LD_CLUST( dj.dir ) ) + { + break; /* Found the entry */ + } + + res = dir_next( &dj, 0 ); + } + while ( res == FR_OK ); + + if ( res == FR_NO_FILE ) + { + res = FR_INT_ERR; /* It cannot be 'not found'. */ + } + + if ( res != FR_OK ) + { + break; + } + #if _USE_LFN - fno.lfname = path; - fno.lfsize = i; + fno.lfname = path; + fno.lfsize = i; #endif - get_fileinfo(&dj, &fno); /* Get the dir name and push it to the buffer */ - tp = fno.fname; - if (_USE_LFN && *path) tp = path; - for (n = 0; tp[n]; n++) ; - if (i < n + 3) { - res = FR_NOT_ENOUGH_CORE; break; - } - while (n) path[--i] = tp[--n]; - path[--i] = '/'; - } - tp = path; - if (res == FR_OK) { - *tp++ = '0' + CurrVol; /* Put drive number */ - *tp++ = ':'; - if (i == sz_path) { /* Root-dir */ - *tp++ = '/'; - } else { /* Sub-dir */ - do /* Add stacked path str */ - *tp++ = path[i++]; - while (i < sz_path); - } - } - *tp = 0; - FREE_BUF(); - } + get_fileinfo( &dj, &fno ); /* Get the dir name and push it to the buffer */ + tp = fno.fname; - LEAVE_FF(dj.fs, res); + if ( _USE_LFN && *path ) + { + tp = path; + } + + for ( n = 0; tp[n]; n++ ) ; + + if ( i < n + 3 ) + { + res = FR_NOT_ENOUGH_CORE; break; + } + + while ( n ) + { + path[--i] = tp[--n]; + } + + path[--i] = '/'; + } + + tp = path; + + if ( res == FR_OK ) + { + *tp++ = '0' + CurrVol; /* Put drive number */ + *tp++ = ':'; + + if ( i == sz_path ) /* Root-dir */ + { + *tp++ = '/'; + } + else /* Sub-dir */ + { + do /* Add stacked path str */ + { + *tp++ = path[i++]; + } + while ( i < sz_path ); + } + } + + *tp = 0; + FREE_BUF(); + } + + LEAVE_FF( dj.fs, res ); } #endif /* _FS_RPATH >= 2 */ #endif /* _FS_RPATH >= 1 */ @@ -2574,174 +3881,312 @@ FRESULT f_getcwd ( /*-----------------------------------------------------------------------*/ FRESULT f_lseek ( - FIL *fp, /* Pointer to the file object */ - DWORD ofs /* File pointer from top of file */ + FIL *fp, /* Pointer to the file object */ + DWORD ofs /* File pointer from top of file */ ) { - FRESULT res; + FRESULT res; - res = validate(fp->fs, fp->id); /* Check validity of the object */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->flag & FA__ERROR) /* Check abort flag */ - LEAVE_FF(fp->fs, FR_INT_ERR); + res = validate( fp->fs, fp->id ); /* Check validity of the object */ + + if ( res != FR_OK ) + { + LEAVE_FF( fp->fs, res ); + } + + if ( fp->flag & FA__ERROR ) /* Check abort flag */ + { + LEAVE_FF( fp->fs, FR_INT_ERR ); + } #if _USE_FASTSEEK - if (fp->cltbl) { /* Fast seek */ - DWORD cl, pcl, ncl, tcl, dsc, tlen, *tbl = fp->cltbl; - BYTE csc; - tlen = *tbl++; - if (ofs == CREATE_LINKMAP) { /* Create link map table */ - cl = fp->org_clust; - if (cl) { - do { - if (tlen < 4) { /* Not enough table items */ - res = FR_NOT_ENOUGH_CORE; break; - } - tcl = cl; ncl = 0; - do { /* Get a fragment and store the top and length */ - pcl = cl; ncl++; - cl = get_fat(fp->fs, cl); - if (cl <= 1) ABORT(fp->fs, FR_INT_ERR); - if (cl == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - } while (cl == pcl + 1); - *tbl++ = ncl; *tbl++ = tcl; - tlen -= 2; - } while (cl < fp->fs->n_fatent); - } - *tbl = 0; /* Terminate table */ + if ( fp->cltbl ) /* Fast seek */ + { + DWORD cl, pcl, ncl, tcl, dsc, tlen, *tbl = fp->cltbl; + BYTE csc; - } else { /* Fast seek */ - if (ofs > fp->fsize) /* Clip offset at the file size */ - ofs = fp->fsize; - fp->fptr = ofs; /* Set file pointer */ - if (ofs) { - dsc = (ofs - 1) / SS(fp->fs); - cl = dsc / fp->fs->csize; - for (;;) { - ncl = *tbl++; - if (!ncl) ABORT(fp->fs, FR_INT_ERR); - if (cl < ncl) break; - cl -= ncl; tbl++; - } - fp->curr_clust = cl + *tbl; - csc = (BYTE)(dsc & (fp->fs->csize - 1)); - dsc = clust2sect(fp->fs, fp->curr_clust); - if (!dsc) ABORT(fp->fs, FR_INT_ERR); - dsc += csc; - if (fp->fptr % SS(fp->fs) && dsc != fp->dsect) { + tlen = *tbl++; + + if ( ofs == CREATE_LINKMAP ) /* Create link map table */ + { + cl = fp->org_clust; + + if ( cl ) + { + do + { + if ( tlen < 4 ) /* Not enough table items */ + { + res = FR_NOT_ENOUGH_CORE; break; + } + + tcl = cl; ncl = 0; + + do /* Get a fragment and store the top and length */ + { + pcl = cl; ncl++; + cl = get_fat( fp->fs, cl ); + + if ( cl <= 1 ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + if ( cl == 0xFFFFFFFF ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + } + while ( cl == pcl + 1 ); + + *tbl++ = ncl; *tbl++ = tcl; + tlen -= 2; + } + while ( cl < fp->fs->n_fatent ); + } + + *tbl = 0; /* Terminate table */ + + } + else /* Fast seek */ + { + if ( ofs > fp->fsize ) /* Clip offset at the file size */ + { + ofs = fp->fsize; + } + + fp->fptr = ofs; /* Set file pointer */ + + if ( ofs ) + { + dsc = ( ofs - 1 ) / SS( fp->fs ); + cl = dsc / fp->fs->csize; + + for ( ;; ) + { + ncl = *tbl++; + + if ( !ncl ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + if ( cl < ncl ) + { + break; + } + + cl -= ncl; tbl++; + } + + fp->curr_clust = cl + *tbl; + csc = ( BYTE )( dsc & ( fp->fs->csize - 1 ) ); + dsc = clust2sect( fp->fs, fp->curr_clust ); + + if ( !dsc ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + dsc += csc; + + if ( fp->fptr % SS( fp->fs ) && dsc != fp->dsect ) + { #if !_FS_TINY #if !_FS_READONLY - if (fp->flag & FA__DIRTY) { /* Flush dirty buffer if needed */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } -#endif - if(!ff_sd_offload) { - sd_offload_partial=0; - if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - } else { - sd_offload_partial=1; - sd_offload_partial_start = fp->fptr % SS(fp->fs); - } -// if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK) -// ABORT(fp->fs, FR_DISK_ERR); -#endif - fp->dsect = dsc; - } - } - } - } else + + if ( fp->flag & FA__DIRTY ) /* Flush dirty buffer if needed */ + { + if ( disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->flag &= ~FA__DIRTY; + } + #endif - /* Normal Seek */ - { - DWORD clst, bcs, nsect, ifptr; + if ( !ff_sd_offload ) + { + sd_offload_partial = 0; - if (ofs > fp->fsize /* In read-only mode, clip offset with the file size */ -#if !_FS_READONLY - && !(fp->flag & FA_WRITE) -#endif - ) ofs = fp->fsize; + if ( disk_read( fp->fs->drv, fp->buf, dsc, 1 ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + } + else + { + sd_offload_partial = 1; + sd_offload_partial_start = fp->fptr % SS( fp->fs ); + } - ifptr = fp->fptr; - fp->fptr = nsect = 0; - if (ofs) { - bcs = (DWORD)fp->fs->csize * SS(fp->fs); /* Cluster size (byte) */ - if (ifptr > 0 && - (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ - fp->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */ - ofs -= fp->fptr; - clst = fp->curr_clust; - } else { /* When seek to back cluster, */ - clst = fp->org_clust; /* start from the first cluster */ -#if !_FS_READONLY - if (clst == 0) { /* If no cluster chain, create a new chain */ - clst = create_chain(fp->fs, 0); - if (clst == 1) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->org_clust = clst; - } + // if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK) + // ABORT(fp->fs, FR_DISK_ERR); #endif - fp->curr_clust = clst; - } - if (clst != 0) { - while (ofs > bcs) { /* Cluster following loop */ -#if !_FS_READONLY - if (fp->flag & FA_WRITE) { /* Check if in write mode or not */ - clst = create_chain(fp->fs, clst); /* Force stretch if in write mode */ - if (clst == 0) { /* When disk gets full, clip file size */ - ofs = bcs; break; - } - } else + fp->dsect = dsc; + } + } + } + } + else #endif - clst = get_fat(fp->fs, clst); /* Follow cluster chain if not in write mode */ - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR); - fp->curr_clust = clst; - fp->fptr += bcs; - ofs -= bcs; - } - fp->fptr += ofs; - if (ofs % SS(fp->fs)) { - nsect = clust2sect(fp->fs, clst); /* Current sector */ - if (!nsect) ABORT(fp->fs, FR_INT_ERR); - nsect += ofs / SS(fp->fs); - } - } - } - if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) { + + /* Normal Seek */ + { + DWORD clst, bcs, nsect, ifptr; + + if ( ofs > fp->fsize /* In read-only mode, clip offset with the file size */ +#if !_FS_READONLY + && !( fp->flag & FA_WRITE ) +#endif + ) + { + ofs = fp->fsize; + } + + ifptr = fp->fptr; + fp->fptr = nsect = 0; + + if ( ofs ) + { + bcs = ( DWORD )fp->fs->csize * SS( fp->fs ); /* Cluster size (byte) */ + + if ( ifptr > 0 && + ( ofs - 1 ) / bcs >= ( ifptr - 1 ) / bcs ) /* When seek to same or following cluster, */ + { + fp->fptr = ( ifptr - 1 ) & ~( bcs - 1 ); /* start from the current cluster */ + ofs -= fp->fptr; + clst = fp->curr_clust; + } + else /* When seek to back cluster, */ + { + clst = fp->org_clust; /* start from the first cluster */ +#if !_FS_READONLY + + if ( clst == 0 ) /* If no cluster chain, create a new chain */ + { + clst = create_chain( fp->fs, 0 ); + + if ( clst == 1 ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + if ( clst == 0xFFFFFFFF ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->org_clust = clst; + } + +#endif + fp->curr_clust = clst; + } + + if ( clst != 0 ) + { + while ( ofs > bcs ) /* Cluster following loop */ + { +#if !_FS_READONLY + + if ( fp->flag & FA_WRITE ) /* Check if in write mode or not */ + { + clst = create_chain( fp->fs, clst ); /* Force stretch if in write mode */ + + if ( clst == 0 ) /* When disk gets full, clip file size */ + { + ofs = bcs; break; + } + } + else +#endif + clst = get_fat( fp->fs, clst ); /* Follow cluster chain if not in write mode */ + + if ( clst == 0xFFFFFFFF ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + if ( clst <= 1 || clst >= fp->fs->n_fatent ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + fp->curr_clust = clst; + fp->fptr += bcs; + ofs -= bcs; + } + + fp->fptr += ofs; + + if ( ofs % SS( fp->fs ) ) + { + nsect = clust2sect( fp->fs, clst ); /* Current sector */ + + if ( !nsect ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + nsect += ofs / SS( fp->fs ); + } + } + } + + if ( fp->fptr % SS( fp->fs ) && nsect != fp->dsect ) + { #if !_FS_TINY #if !_FS_READONLY - if (fp->flag & FA__DIRTY) { /* Flush dirty buffer if needed */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } + + if ( fp->flag & FA__DIRTY ) /* Flush dirty buffer if needed */ + { + if ( disk_write( fp->fs->drv, fp->buf, fp->dsect, 1 ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->flag &= ~FA__DIRTY; + } + #endif - if(!ff_sd_offload) { - sd_offload_partial=0; - if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - } else { - sd_offload_partial=1; - sd_offload_partial_start = fp->fptr % SS(fp->fs); - } + + if ( !ff_sd_offload ) + { + sd_offload_partial = 0; + + if ( disk_read( fp->fs->drv, fp->buf, nsect, 1 ) != RES_OK ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + } + else + { + sd_offload_partial = 1; + sd_offload_partial_start = fp->fptr % SS( fp->fs ); + } + #endif - fp->dsect = nsect; - } + fp->dsect = nsect; + } + #if !_FS_READONLY - if (fp->fptr > fp->fsize) { /* Set change flag if the file size is extended */ - fp->fsize = fp->fptr; - fp->flag |= FA__WRITTEN; - } + + if ( fp->fptr > fp->fsize ) /* Set change flag if the file size is extended */ + { + fp->fsize = fp->fptr; + fp->flag |= FA__WRITTEN; + } + #endif - } - ff_sd_offload = 0; - LEAVE_FF(fp->fs, res); + } + + ff_sd_offload = 0; + LEAVE_FF( fp->fs, res ); } @@ -2752,36 +4197,50 @@ FRESULT f_lseek ( /*-----------------------------------------------------------------------*/ FRESULT f_opendir ( - DIR *dj, /* Pointer to directory object to create */ - const TCHAR *path /* Pointer to the directory path */ + DIR *dj, /* Pointer to directory object to create */ + const TCHAR *path /* Pointer to the directory path */ ) { - FRESULT res; - DEF_NAMEBUF; + FRESULT res; + DEF_NAMEBUF; - res = chk_mounted(&path, &dj->fs, 0); - if (res == FR_OK) { - INIT_BUF(*dj); - res = follow_path(dj, path); /* Follow the path to the directory */ - FREE_BUF(); - if (res == FR_OK) { /* Follow completed */ - if (dj->dir) { /* It is not the root dir */ - if (dj->dir[DIR_Attr] & AM_DIR) { /* The object is a directory */ - dj->sclust = LD_CLUST(dj->dir); - } else { /* The object is not a directory */ - res = FR_NO_PATH; - } - } - if (res == FR_OK) { - dj->id = dj->fs->id; - res = dir_sdi(dj, 0); /* Rewind dir */ - } - } - if (res == FR_NO_FILE) res = FR_NO_PATH; - } + res = chk_mounted( &path, &dj->fs, 0 ); - LEAVE_FF(dj->fs, res); + if ( res == FR_OK ) + { + INIT_BUF( *dj ); + res = follow_path( dj, path ); /* Follow the path to the directory */ + FREE_BUF(); + + if ( res == FR_OK ) /* Follow completed */ + { + if ( dj->dir ) /* It is not the root dir */ + { + if ( dj->dir[DIR_Attr] & AM_DIR ) /* The object is a directory */ + { + dj->sclust = LD_CLUST( dj->dir ); + } + else /* The object is not a directory */ + { + res = FR_NO_PATH; + } + } + + if ( res == FR_OK ) + { + dj->id = dj->fs->id; + res = dir_sdi( dj, 0 ); /* Rewind dir */ + } + } + + if ( res == FR_NO_FILE ) + { + res = FR_NO_PATH; + } + } + + LEAVE_FF( dj->fs, res ); } @@ -2792,78 +4251,90 @@ FRESULT f_opendir ( /*-----------------------------------------------------------------------*/ FRESULT f_readdir ( - DIR *dj, /* Pointer to the open directory object */ - FILINFO *fno /* Pointer to file information to return */ + DIR *dj, /* Pointer to the open directory object */ + FILINFO *fno /* Pointer to file information to return */ ) { - FRESULT res; - DEF_NAMEBUF; + FRESULT res; + DEF_NAMEBUF; - res = validate(dj->fs, dj->id); /* Check validity of the object */ - if (res == FR_OK) { - if (!fno) { - res = dir_sdi(dj, 0); /* Rewind the directory object */ - } else { - INIT_BUF(*dj); - res = dir_read(dj); /* Read an directory item */ - if (res == FR_NO_FILE) { /* Reached end of dir */ - dj->sect = 0; - res = FR_OK; - } - if (res == FR_OK) { /* A valid entry is found */ - get_fileinfo(dj, fno); /* Get the object information */ - res = dir_next(dj, 0); /* Increment index for next */ - if (res == FR_NO_FILE) { - dj->sect = 0; - res = FR_OK; - } - } - FREE_BUF(); - } - } + res = validate( dj->fs, dj->id ); /* Check validity of the object */ - LEAVE_FF(dj->fs, res); + if ( res == FR_OK ) + { + if ( !fno ) + { + res = dir_sdi( dj, 0 ); /* Rewind the directory object */ + } + else + { + INIT_BUF( *dj ); + res = dir_read( dj ); /* Read an directory item */ + + if ( res == FR_NO_FILE ) /* Reached end of dir */ + { + dj->sect = 0; + res = FR_OK; + } + + if ( res == FR_OK ) /* A valid entry is found */ + { + get_fileinfo( dj, fno ); /* Get the object information */ + res = dir_next( dj, 0 ); /* Increment index for next */ + + if ( res == FR_NO_FILE ) + { + dj->sect = 0; + res = FR_OK; + } + } + + FREE_BUF(); + } + } + + LEAVE_FF( dj->fs, res ); } FRESULT l_opendirbycluster ( - FATFS *fs, - DIR *dj, - const TCHAR *path, - DWORD clust + FATFS *fs, + DIR *dj, + const TCHAR *path, + DWORD clust ) { - FRESULT res; - res = chk_mounted(&path, &fs, 0); - DEF_NAMEBUF; - INIT_BUF(*dj); - dj->sclust = clust; - dj->fs = fs; - dj->id = fs->id; - dj->dir = 0; - res = dir_sdi(dj, 0); - FREE_BUF(); - return res; + FRESULT res; + res = chk_mounted( &path, &fs, 0 ); + DEF_NAMEBUF; + INIT_BUF( *dj ); + dj->sclust = clust; + dj->fs = fs; + dj->id = fs->id; + dj->dir = 0; + res = dir_sdi( dj, 0 ); + FREE_BUF(); + return res; } FRESULT l_openfilebycluster ( - FATFS *fs, /* Pointer to file system object */ - FIL *fp, /* Pointer to the blank file object */ - const TCHAR *path, - DWORD clust, /* Cluster number to be opened */ - DWORD fsize /* File size to be assumed */ + FATFS *fs, /* Pointer to file system object */ + FIL *fp, /* Pointer to the blank file object */ + const TCHAR *path, + DWORD clust, /* Cluster number to be opened */ + DWORD fsize /* File size to be assumed */ ) { - chk_mounted(&path, &fs, 0); - fp->flag = FA_READ; - fp->org_clust = clust; - fp->fsize = fsize; - fp->fptr = 0; - fp->dsect = 0; - fp->fs = fs; + chk_mounted( &path, &fs, 0 ); + fp->flag = FA_READ; + fp->org_clust = clust; + fp->fsize = fsize; + fp->fptr = 0; + fp->dsect = 0; + fp->fs = fs; - return FR_OK; + return FR_OK; } @@ -2874,29 +4345,38 @@ FRESULT l_openfilebycluster ( /*-----------------------------------------------------------------------*/ FRESULT f_stat ( - const TCHAR *path, /* Pointer to the file path */ - FILINFO *fno /* Pointer to file information to return */ + const TCHAR *path, /* Pointer to the file path */ + FILINFO *fno /* Pointer to file information to return */ ) { - FRESULT res; - DIR dj; - DEF_NAMEBUF; + FRESULT res; + DIR dj; + DEF_NAMEBUF; - res = chk_mounted(&path, &dj.fs, 0); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - if (res == FR_OK) { /* Follow completed */ - if (dj.dir) /* Found an object */ - get_fileinfo(&dj, fno); - else /* It is root dir */ - res = FR_INVALID_NAME; - } - FREE_BUF(); - } + res = chk_mounted( &path, &dj.fs, 0 ); - LEAVE_FF(dj.fs, res); + if ( res == FR_OK ) + { + INIT_BUF( dj ); + res = follow_path( &dj, path ); /* Follow the file path */ + + if ( res == FR_OK ) /* Follow completed */ + { + if ( dj.dir ) /* Found an object */ + { + get_fileinfo( &dj, fno ); + } + else /* It is root dir */ + { + res = FR_INVALID_NAME; + } + } + + FREE_BUF(); + } + + LEAVE_FF( dj.fs, res ); } #if !_FS_READONLY @@ -2905,61 +4385,115 @@ FRESULT f_stat ( /*-----------------------------------------------------------------------*/ FRESULT f_getfree ( - const TCHAR *path, /* Pointer to the logical drive number (root dir) */ - DWORD *nclst, /* Pointer to the variable to return number of free clusters */ - FATFS **fatfs /* Pointer to pointer to corresponding file system object to return */ + const TCHAR *path, /* Pointer to the logical drive number (root dir) */ + DWORD *nclst, /* Pointer to the variable to return number of free clusters */ + FATFS **fatfs /* Pointer to pointer to corresponding file system object to return */ ) { - FRESULT res; - DWORD n, clst, sect, stat; - UINT i; - BYTE fat, *p; + FRESULT res; + DWORD n, clst, sect, stat; + UINT i; + BYTE fat, *p; - /* Get drive number */ - res = chk_mounted(&path, fatfs, 0); - if (res == FR_OK) { - /* If free_clust is valid, return it without full cluster scan */ - if ((*fatfs)->free_clust <= (*fatfs)->n_fatent - 2) { - *nclst = (*fatfs)->free_clust; - } else { - /* Get number of free clusters */ - fat = (*fatfs)->fs_type; - n = 0; - if (fat == FS_FAT12) { - clst = 2; - do { - stat = get_fat(*fatfs, clst); - if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } - if (stat == 1) { res = FR_INT_ERR; break; } - if (stat == 0) n++; - } while (++clst < (*fatfs)->n_fatent); - } else { - clst = (*fatfs)->n_fatent; - sect = (*fatfs)->fatbase; - i = 0; p = 0; - do { - if (!i) { - res = move_window(*fatfs, sect++); - if (res != FR_OK) break; - p = (*fatfs)->win; - i = SS(*fatfs); - } - if (fat == FS_FAT16) { - if (LD_WORD(p) == 0) n++; - p += 2; i -= 2; - } else { - if ((LD_DWORD(p) & 0x0FFFFFFF) == 0) n++; - p += 4; i -= 4; - } - } while (--clst); - } - (*fatfs)->free_clust = n; - if (fat == FS_FAT32) (*fatfs)->fsi_flag = 1; - *nclst = n; - } - } - LEAVE_FF(*fatfs, res); + /* Get drive number */ + res = chk_mounted( &path, fatfs, 0 ); + + if ( res == FR_OK ) + { + /* If free_clust is valid, return it without full cluster scan */ + if ( ( *fatfs )->free_clust <= ( *fatfs )->n_fatent - 2 ) + { + *nclst = ( *fatfs )->free_clust; + } + else + { + /* Get number of free clusters */ + fat = ( *fatfs )->fs_type; + n = 0; + + if ( fat == FS_FAT12 ) + { + clst = 2; + + do + { + stat = get_fat( *fatfs, clst ); + + if ( stat == 0xFFFFFFFF ) + { + res = FR_DISK_ERR; + break; + } + + if ( stat == 1 ) + { + res = FR_INT_ERR; + break; + } + + if ( stat == 0 ) + { + n++; + } + } + while ( ++clst < ( *fatfs )->n_fatent ); + } + else + { + clst = ( *fatfs )->n_fatent; + sect = ( *fatfs )->fatbase; + i = 0; p = 0; + + do + { + if ( !i ) + { + res = move_window( *fatfs, sect++ ); + + if ( res != FR_OK ) + { + break; + } + + p = ( *fatfs )->win; + i = SS( *fatfs ); + } + + if ( fat == FS_FAT16 ) + { + if ( LD_WORD( p ) == 0 ) + { + n++; + } + + p += 2; i -= 2; + } + else + { + if ( ( LD_DWORD( p ) & 0x0FFFFFFF ) == 0 ) + { + n++; + } + + p += 4; i -= 4; + } + } + while ( --clst ); + } + + ( *fatfs )->free_clust = n; + + if ( fat == FS_FAT32 ) + { + ( *fatfs )->fsi_flag = 1; + } + + *nclst = n; + } + } + + LEAVE_FF( *fatfs, res ); } @@ -2970,44 +4504,76 @@ FRESULT f_getfree ( /*-----------------------------------------------------------------------*/ FRESULT f_truncate ( - FIL *fp /* Pointer to the file object */ + FIL *fp /* Pointer to the file object */ ) { - FRESULT res; - DWORD ncl; + FRESULT res; + DWORD ncl; - res = validate(fp->fs, fp->id); /* Check validity of the object */ - if (res == FR_OK) { - if (fp->flag & FA__ERROR) { /* Check abort flag */ - res = FR_INT_ERR; - } else { - if (!(fp->flag & FA_WRITE)) /* Check access mode */ - res = FR_DENIED; - } - } - if (res == FR_OK) { - if (fp->fsize > fp->fptr) { - fp->fsize = fp->fptr; /* Set file size to current R/W point */ - fp->flag |= FA__WRITTEN; - if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */ - res = remove_chain(fp->fs, fp->org_clust); - fp->org_clust = 0; - } else { /* When truncate a part of the file, remove remaining clusters */ - ncl = get_fat(fp->fs, fp->curr_clust); - res = FR_OK; - if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; - if (ncl == 1) res = FR_INT_ERR; - if (res == FR_OK && ncl < fp->fs->n_fatent) { - res = put_fat(fp->fs, fp->curr_clust, 0x0FFFFFFF); - if (res == FR_OK) res = remove_chain(fp->fs, ncl); - } - } - } - if (res != FR_OK) fp->flag |= FA__ERROR; - } + res = validate( fp->fs, fp->id ); /* Check validity of the object */ - LEAVE_FF(fp->fs, res); + if ( res == FR_OK ) + { + if ( fp->flag & FA__ERROR ) /* Check abort flag */ + { + res = FR_INT_ERR; + } + else + { + if ( !( fp->flag & FA_WRITE ) ) /* Check access mode */ + { + res = FR_DENIED; + } + } + } + + if ( res == FR_OK ) + { + if ( fp->fsize > fp->fptr ) + { + fp->fsize = fp->fptr; /* Set file size to current R/W point */ + fp->flag |= FA__WRITTEN; + + if ( fp->fptr == 0 ) /* When set file size to zero, remove entire cluster chain */ + { + res = remove_chain( fp->fs, fp->org_clust ); + fp->org_clust = 0; + } + else /* When truncate a part of the file, remove remaining clusters */ + { + ncl = get_fat( fp->fs, fp->curr_clust ); + res = FR_OK; + + if ( ncl == 0xFFFFFFFF ) + { + res = FR_DISK_ERR; + } + + if ( ncl == 1 ) + { + res = FR_INT_ERR; + } + + if ( res == FR_OK && ncl < fp->fs->n_fatent ) + { + res = put_fat( fp->fs, fp->curr_clust, 0x0FFFFFFF ); + + if ( res == FR_OK ) + { + res = remove_chain( fp->fs, ncl ); + } + } + } + } + + if ( res != FR_OK ) + { + fp->flag |= FA__ERROR; + } + } + + LEAVE_FF( fp->fs, res ); } @@ -3018,64 +4584,111 @@ FRESULT f_truncate ( /*-----------------------------------------------------------------------*/ FRESULT f_unlink ( - const TCHAR *path /* Pointer to the file or directory path */ + const TCHAR *path /* Pointer to the file or directory path */ ) { - FRESULT res; - DIR dj, sdj; - BYTE *dir; - DWORD dclst; - DEF_NAMEBUF; + FRESULT res; + DIR dj, sdj; + BYTE *dir; + DWORD dclst; + DEF_NAMEBUF; - res = chk_mounted(&path, &dj.fs, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; /* Cannot remove dot entry */ + res = chk_mounted( &path, &dj.fs, 1 ); + + if ( res == FR_OK ) + { + INIT_BUF( dj ); + res = follow_path( &dj, path ); /* Follow the file path */ + + if ( _FS_RPATH && res == FR_OK && ( dj.fn[NS] & NS_DOT ) ) + { + res = FR_INVALID_NAME; /* Cannot remove dot entry */ + } + #if _FS_SHARE - if (res == FR_OK) res = chk_lock(&dj, 2); /* Cannot remove open file */ + + if ( res == FR_OK ) + { + res = chk_lock( &dj, 2 ); /* Cannot remove open file */ + } + #endif - if (res == FR_OK) { /* The object is accessible */ - dir = dj.dir; - if (!dir) { - res = FR_INVALID_NAME; /* Cannot remove the start directory */ - } else { - if (dir[DIR_Attr] & AM_RDO) - res = FR_DENIED; /* Cannot remove R/O object */ - } - dclst = LD_CLUST(dir); - if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-dir? */ - if (dclst < 2) { - res = FR_INT_ERR; - } else { - mem_cpy(&sdj, &dj, sizeof(DIR)); /* Check if the sub-dir is empty or not */ - sdj.sclust = dclst; - res = dir_sdi(&sdj, 2); /* Exclude dot entries */ - if (res == FR_OK) { - res = dir_read(&sdj); - if (res == FR_OK /* Not empty dir */ + + if ( res == FR_OK ) /* The object is accessible */ + { + dir = dj.dir; + + if ( !dir ) + { + res = FR_INVALID_NAME; /* Cannot remove the start directory */ + } + else + { + if ( dir[DIR_Attr] & AM_RDO ) + { + res = FR_DENIED; /* Cannot remove R/O object */ + } + } + + dclst = LD_CLUST( dir ); + + if ( res == FR_OK && ( dir[DIR_Attr] & AM_DIR ) ) /* Is it a sub-dir? */ + { + if ( dclst < 2 ) + { + res = FR_INT_ERR; + } + else + { + mem_cpy( &sdj, &dj, sizeof( DIR ) ); /* Check if the sub-dir is empty or not */ + sdj.sclust = dclst; + res = dir_sdi( &sdj, 2 ); /* Exclude dot entries */ + + if ( res == FR_OK ) + { + res = dir_read( &sdj ); + + if ( res == FR_OK /* Not empty dir */ #if _FS_RPATH - || dclst == sdj.fs->cdir /* Current dir */ + || dclst == sdj.fs->cdir /* Current dir */ #endif - ) res = FR_DENIED; - if (res == FR_NO_FILE) res = FR_OK; /* Empty */ - } - } - } - if (res == FR_OK) { - res = dir_remove(&dj); /* Remove the directory entry */ - if (res == FR_OK) { - if (dclst) /* Remove the cluster chain if exist */ - res = remove_chain(dj.fs, dclst); - if (res == FR_OK) res = sync(dj.fs); - } - } - } - FREE_BUF(); - } - LEAVE_FF(dj.fs, res); + ) + { + res = FR_DENIED; + } + + if ( res == FR_NO_FILE ) + { + res = FR_OK; /* Empty */ + } + } + } + } + + if ( res == FR_OK ) + { + res = dir_remove( &dj ); /* Remove the directory entry */ + + if ( res == FR_OK ) + { + if ( dclst ) /* Remove the cluster chain if exist */ + { + res = remove_chain( dj.fs, dclst ); + } + + if ( res == FR_OK ) + { + res = sync( dj.fs ); + } + } + } + } + + FREE_BUF(); + } + + LEAVE_FF( dj.fs, res ); } @@ -3086,69 +4699,117 @@ FRESULT f_unlink ( /*-----------------------------------------------------------------------*/ FRESULT f_mkdir ( - const TCHAR *path /* Pointer to the directory path */ + const TCHAR *path /* Pointer to the directory path */ ) { - FRESULT res; - DIR dj; - BYTE *dir, n; - DWORD dsc, dcl, pcl, tim = get_fattime(); - DEF_NAMEBUF; + FRESULT res; + DIR dj; + BYTE *dir, n; + DWORD dsc, dcl, pcl, tim = get_fattime(); + DEF_NAMEBUF; - res = chk_mounted(&path, &dj.fs, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */ - if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; - if (res == FR_NO_FILE) { /* Can create a new directory */ - dcl = create_chain(dj.fs, 0); /* Allocate a cluster for the new directory table */ - res = FR_OK; - if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */ - if (dcl == 1) res = FR_INT_ERR; - if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; - if (res == FR_OK) /* Flush FAT */ - res = move_window(dj.fs, 0); - if (res == FR_OK) { /* Initialize the new directory table */ - dsc = clust2sect(dj.fs, dcl); - dir = dj.fs->win; - mem_set(dir, 0, SS(dj.fs)); - mem_set(dir+DIR_Name, ' ', 8+3); /* Create "." entry */ - dir[DIR_Name] = '.'; - dir[DIR_Attr] = AM_DIR; - ST_DWORD(dir+DIR_WrtTime, tim); - ST_CLUST(dir, dcl); - mem_cpy(dir+32, dir, 32); /* Create ".." entry */ - dir[33] = '.'; pcl = dj.sclust; - if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase) - pcl = 0; - ST_CLUST(dir+32, pcl); - for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */ - dj.fs->winsect = dsc++; - dj.fs->wflag = 1; - res = move_window(dj.fs, 0); - if (res != FR_OK) break; - mem_set(dir, 0, SS(dj.fs)); - } - } - if (res == FR_OK) res = dir_register(&dj); /* Register the object to the directoy */ - if (res != FR_OK) { - remove_chain(dj.fs, dcl); /* Could not register, remove cluster chain */ - } else { - dir = dj.dir; - dir[DIR_Attr] = AM_DIR; /* Attribute */ - ST_DWORD(dir+DIR_WrtTime, tim); /* Created time */ - ST_CLUST(dir, dcl); /* Table start cluster */ - dj.fs->wflag = 1; - res = sync(dj.fs); - } - } - FREE_BUF(); - } + res = chk_mounted( &path, &dj.fs, 1 ); - LEAVE_FF(dj.fs, res); + if ( res == FR_OK ) + { + INIT_BUF( dj ); + res = follow_path( &dj, path ); /* Follow the file path */ + + if ( res == FR_OK ) + { + res = FR_EXIST; /* Any object with same name is already existing */ + } + + if ( _FS_RPATH && res == FR_NO_FILE && ( dj.fn[NS] & NS_DOT ) ) + { + res = FR_INVALID_NAME; + } + + if ( res == FR_NO_FILE ) /* Can create a new directory */ + { + dcl = create_chain( dj.fs, 0 ); /* Allocate a cluster for the new directory table */ + res = FR_OK; + + if ( dcl == 0 ) + { + res = FR_DENIED; /* No space to allocate a new cluster */ + } + + if ( dcl == 1 ) + { + res = FR_INT_ERR; + } + + if ( dcl == 0xFFFFFFFF ) + { + res = FR_DISK_ERR; + } + + if ( res == FR_OK ) /* Flush FAT */ + { + res = move_window( dj.fs, 0 ); + } + + if ( res == FR_OK ) /* Initialize the new directory table */ + { + dsc = clust2sect( dj.fs, dcl ); + dir = dj.fs->win; + mem_set( dir, 0, SS( dj.fs ) ); + mem_set( dir + DIR_Name, ' ', 8 + 3 ); /* Create "." entry */ + dir[DIR_Name] = '.'; + dir[DIR_Attr] = AM_DIR; + ST_DWORD( dir + DIR_WrtTime, tim ); + ST_CLUST( dir, dcl ); + mem_cpy( dir + 32, dir, 32 ); /* Create ".." entry */ + dir[33] = '.'; pcl = dj.sclust; + + if ( dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase ) + { + pcl = 0; + } + + ST_CLUST( dir + 32, pcl ); + + for ( n = dj.fs->csize; n; n-- ) /* Write dot entries and clear following sectors */ + { + dj.fs->winsect = dsc++; + dj.fs->wflag = 1; + res = move_window( dj.fs, 0 ); + + if ( res != FR_OK ) + { + break; + } + + mem_set( dir, 0, SS( dj.fs ) ); + } + } + + if ( res == FR_OK ) + { + res = dir_register( &dj ); /* Register the object to the directoy */ + } + + if ( res != FR_OK ) + { + remove_chain( dj.fs, dcl ); /* Could not register, remove cluster chain */ + } + else + { + dir = dj.dir; + dir[DIR_Attr] = AM_DIR; /* Attribute */ + ST_DWORD( dir + DIR_WrtTime, tim ); /* Created time */ + ST_CLUST( dir, dcl ); /* Table start cluster */ + dj.fs->wflag = 1; + res = sync( dj.fs ); + } + } + + FREE_BUF(); + } + + LEAVE_FF( dj.fs, res ); } @@ -3159,38 +4820,49 @@ FRESULT f_mkdir ( /*-----------------------------------------------------------------------*/ FRESULT f_chmod ( - const TCHAR *path, /* Pointer to the file path */ - BYTE value, /* Attribute bits */ - BYTE mask /* Attribute mask to change */ + const TCHAR *path, /* Pointer to the file path */ + BYTE value, /* Attribute bits */ + BYTE mask /* Attribute mask to change */ ) { - FRESULT res; - DIR dj; - BYTE *dir; - DEF_NAMEBUF; + FRESULT res; + DIR dj; + BYTE *dir; + DEF_NAMEBUF; - res = chk_mounted(&path, &dj.fs, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - FREE_BUF(); - if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; - if (res == FR_OK) { - dir = dj.dir; - if (!dir) { /* Is it a root directory? */ - res = FR_INVALID_NAME; - } else { /* File or sub directory */ - mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */ - dir[DIR_Attr] = (value & mask) | (dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */ - dj.fs->wflag = 1; - res = sync(dj.fs); - } - } - } + res = chk_mounted( &path, &dj.fs, 1 ); - LEAVE_FF(dj.fs, res); + if ( res == FR_OK ) + { + INIT_BUF( dj ); + res = follow_path( &dj, path ); /* Follow the file path */ + FREE_BUF(); + + if ( _FS_RPATH && res == FR_OK && ( dj.fn[NS] & NS_DOT ) ) + { + res = FR_INVALID_NAME; + } + + if ( res == FR_OK ) + { + dir = dj.dir; + + if ( !dir ) /* Is it a root directory? */ + { + res = FR_INVALID_NAME; + } + else /* File or sub directory */ + { + mask &= AM_RDO | AM_HID | AM_SYS | AM_ARC; /* Valid attribute mask */ + dir[DIR_Attr] = ( value & mask ) | ( dir[DIR_Attr] & ( BYTE )~mask ); /* Apply attribute change */ + dj.fs->wflag = 1; + res = sync( dj.fs ); + } + } + } + + LEAVE_FF( dj.fs, res ); } @@ -3201,37 +4873,48 @@ FRESULT f_chmod ( /*-----------------------------------------------------------------------*/ FRESULT f_utime ( - const TCHAR *path, /* Pointer to the file/directory name */ - const FILINFO *fno /* Pointer to the time stamp to be set */ + const TCHAR *path, /* Pointer to the file/directory name */ + const FILINFO *fno /* Pointer to the time stamp to be set */ ) { - FRESULT res; - DIR dj; - BYTE *dir; - DEF_NAMEBUF; + FRESULT res; + DIR dj; + BYTE *dir; + DEF_NAMEBUF; - res = chk_mounted(&path, &dj.fs, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - FREE_BUF(); - if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; - if (res == FR_OK) { - dir = dj.dir; - if (!dir) { /* Root directory */ - res = FR_INVALID_NAME; - } else { /* File or sub-directory */ - ST_WORD(dir+DIR_WrtTime, fno->ftime); - ST_WORD(dir+DIR_WrtDate, fno->fdate); - dj.fs->wflag = 1; - res = sync(dj.fs); - } - } - } + res = chk_mounted( &path, &dj.fs, 1 ); - LEAVE_FF(dj.fs, res); + if ( res == FR_OK ) + { + INIT_BUF( dj ); + res = follow_path( &dj, path ); /* Follow the file path */ + FREE_BUF(); + + if ( _FS_RPATH && res == FR_OK && ( dj.fn[NS] & NS_DOT ) ) + { + res = FR_INVALID_NAME; + } + + if ( res == FR_OK ) + { + dir = dj.dir; + + if ( !dir ) /* Root directory */ + { + res = FR_INVALID_NAME; + } + else /* File or sub-directory */ + { + ST_WORD( dir + DIR_WrtTime, fno->ftime ); + ST_WORD( dir + DIR_WrtDate, fno->fdate ); + dj.fs->wflag = 1; + res = sync( dj.fs ); + } + } + } + + LEAVE_FF( dj.fs, res ); } @@ -3242,70 +4925,110 @@ FRESULT f_utime ( /*-----------------------------------------------------------------------*/ FRESULT f_rename ( - const TCHAR *path_old, /* Pointer to the old name */ - const TCHAR *path_new /* Pointer to the new name */ + const TCHAR *path_old, /* Pointer to the old name */ + const TCHAR *path_new /* Pointer to the new name */ ) { - FRESULT res; - DIR djo, djn; - BYTE buf[21], *dir; - DWORD dw; - DEF_NAMEBUF; + FRESULT res; + DIR djo, djn; + BYTE buf[21], *dir; + DWORD dw; + DEF_NAMEBUF; - res = chk_mounted(&path_old, &djo.fs, 1); - if (res == FR_OK) { - djn.fs = djo.fs; - INIT_BUF(djo); - res = follow_path(&djo, path_old); /* Check old object */ - if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; + res = chk_mounted( &path_old, &djo.fs, 1 ); + + if ( res == FR_OK ) + { + djn.fs = djo.fs; + INIT_BUF( djo ); + res = follow_path( &djo, path_old ); /* Check old object */ + + if ( _FS_RPATH && res == FR_OK && ( djo.fn[NS] & NS_DOT ) ) + { + res = FR_INVALID_NAME; + } + #if _FS_SHARE - if (res == FR_OK) res = chk_lock(&djo, 2); + + if ( res == FR_OK ) + { + res = chk_lock( &djo, 2 ); + } + #endif - if (res == FR_OK) { /* Old object is found */ - if (!djo.dir) { /* Is root dir? */ - res = FR_NO_FILE; - } else { - mem_cpy(buf, djo.dir+DIR_Attr, 21); /* Save the object information except for name */ - mem_cpy(&djn, &djo, sizeof(DIR)); /* Check new object */ - res = follow_path(&djn, path_new); - if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */ - if (res == FR_NO_FILE) { /* Is it a valid path and no name collision? */ -/* Start critical section that any interruption or error can cause cross-link */ - res = dir_register(&djn); /* Register the new entry */ - if (res == FR_OK) { - dir = djn.dir; /* Copy object information except for name */ - mem_cpy(dir+13, buf+2, 19); - dir[DIR_Attr] = buf[0] | AM_ARC; - djo.fs->wflag = 1; - if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) { /* Update .. entry in the directory if needed */ - dw = clust2sect(djn.fs, LD_CLUST(dir)); - if (!dw) { - res = FR_INT_ERR; - } else { - res = move_window(djn.fs, dw); - dir = djn.fs->win+32; /* .. entry */ - if (res == FR_OK && dir[1] == '.') { - dw = (djn.fs->fs_type == FS_FAT32 && djn.sclust == djn.fs->dirbase) ? 0 : djn.sclust; - ST_CLUST(dir, dw); - djn.fs->wflag = 1; - } - } - } - if (res == FR_OK) { - res = dir_remove(&djo); /* Remove old entry */ - if (res == FR_OK) - res = sync(djo.fs); - } - } -/* End critical section */ - } - } - } - FREE_BUF(); - } - LEAVE_FF(djo.fs, res); + + if ( res == FR_OK ) /* Old object is found */ + { + if ( !djo.dir ) /* Is root dir? */ + { + res = FR_NO_FILE; + } + else + { + mem_cpy( buf, djo.dir + DIR_Attr, 21 ); /* Save the object information except for name */ + mem_cpy( &djn, &djo, sizeof( DIR ) ); /* Check new object */ + res = follow_path( &djn, path_new ); + + if ( res == FR_OK ) + { + res = FR_EXIST; /* The new object name is already existing */ + } + + if ( res == FR_NO_FILE ) /* Is it a valid path and no name collision? */ + { + /* Start critical section that any interruption or error can cause cross-link */ + res = dir_register( &djn ); /* Register the new entry */ + + if ( res == FR_OK ) + { + dir = djn.dir; /* Copy object information except for name */ + mem_cpy( dir + 13, buf + 2, 19 ); + dir[DIR_Attr] = buf[0] | AM_ARC; + djo.fs->wflag = 1; + + if ( djo.sclust != djn.sclust && ( dir[DIR_Attr] & AM_DIR ) ) /* Update .. entry in the directory if needed */ + { + dw = clust2sect( djn.fs, LD_CLUST( dir ) ); + + if ( !dw ) + { + res = FR_INT_ERR; + } + else + { + res = move_window( djn.fs, dw ); + dir = djn.fs->win + 32; /* .. entry */ + + if ( res == FR_OK && dir[1] == '.' ) + { + dw = ( djn.fs->fs_type == FS_FAT32 && djn.sclust == djn.fs->dirbase ) ? 0 : djn.sclust; + ST_CLUST( dir, dw ); + djn.fs->wflag = 1; + } + } + } + + if ( res == FR_OK ) + { + res = dir_remove( &djo ); /* Remove old entry */ + + if ( res == FR_OK ) + { + res = sync( djo.fs ); + } + } + } + + /* End critical section */ + } + } + } + + FREE_BUF(); + } + + LEAVE_FF( djo.fs, res ); } #endif /* !_FS_READONLY */ @@ -3321,55 +5044,101 @@ FRESULT f_rename ( #if _USE_FORWARD && _FS_TINY FRESULT f_forward ( - FIL *fp, /* Pointer to the file object */ - UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */ - UINT btr, /* Number of bytes to forward */ - UINT *bf /* Pointer to number of bytes forwarded */ + FIL *fp, /* Pointer to the file object */ + UINT ( *func )( const BYTE *, UINT ), /* Pointer to the streaming function */ + UINT btr, /* Number of bytes to forward */ + UINT *bf /* Pointer to number of bytes forwarded */ ) { - FRESULT res; - DWORD remain, clst, sect; - UINT rcnt; - BYTE csect; + FRESULT res; + DWORD remain, clst, sect; + UINT rcnt; + BYTE csect; - *bf = 0; /* Initialize byte counter */ + *bf = 0; /* Initialize byte counter */ - res = validate(fp->fs, fp->id); /* Check validity of the object */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->flag & FA__ERROR) /* Check error flag */ - LEAVE_FF(fp->fs, FR_INT_ERR); - if (!(fp->flag & FA_READ)) /* Check access mode */ - LEAVE_FF(fp->fs, FR_DENIED); + res = validate( fp->fs, fp->id ); /* Check validity of the object */ - remain = fp->fsize - fp->fptr; - if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ + if ( res != FR_OK ) + { + LEAVE_FF( fp->fs, res ); + } - for ( ; btr && (*func)(0, 0); /* Repeat until all data transferred or stream becomes busy */ - fp->fptr += rcnt, *bf += rcnt, btr -= rcnt) { - csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ - if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - if (!csect) { /* On the cluster boundary? */ - clst = (fp->fptr == 0) ? /* On the top of the file? */ - fp->org_clust : get_fat(fp->fs, fp->curr_clust); - if (clst <= 1) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->curr_clust = clst; /* Update current cluster */ - } - } - sect = clust2sect(fp->fs, fp->curr_clust); /* Get current data sector */ - if (!sect) ABORT(fp->fs, FR_INT_ERR); - sect += csect; - if (move_window(fp->fs, sect)) /* Move sector window */ - ABORT(fp->fs, FR_DISK_ERR); - fp->dsect = sect; - rcnt = SS(fp->fs) - (WORD)(fp->fptr % SS(fp->fs)); /* Forward data from sector window */ - if (rcnt > btr) rcnt = btr; - rcnt = (*func)(&fp->fs->win[(WORD)fp->fptr % SS(fp->fs)], rcnt); - if (!rcnt) ABORT(fp->fs, FR_INT_ERR); - } + if ( fp->flag & FA__ERROR ) /* Check error flag */ + { + LEAVE_FF( fp->fs, FR_INT_ERR ); + } - LEAVE_FF(fp->fs, FR_OK); + if ( !( fp->flag & FA_READ ) ) /* Check access mode */ + { + LEAVE_FF( fp->fs, FR_DENIED ); + } + + remain = fp->fsize - fp->fptr; + + if ( btr > remain ) + { + btr = ( UINT )remain; /* Truncate btr by remaining bytes */ + } + + for ( ; btr && ( *func )( 0, 0 ); /* Repeat until all data transferred or stream becomes busy */ + fp->fptr += rcnt, *bf += rcnt, btr -= rcnt ) + { + csect = ( BYTE )( fp->fptr / SS( fp->fs ) & ( fp->fs->csize - 1 ) ); /* Sector offset in the cluster */ + + if ( ( fp->fptr % SS( fp->fs ) ) == 0 ) /* On the sector boundary? */ + { + if ( !csect ) /* On the cluster boundary? */ + { + clst = ( fp->fptr == 0 ) ? /* On the top of the file? */ + fp->org_clust : get_fat( fp->fs, fp->curr_clust ); + + if ( clst <= 1 ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + if ( clst == 0xFFFFFFFF ) + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->curr_clust = clst; /* Update current cluster */ + } + } + + sect = clust2sect( fp->fs, fp->curr_clust ); /* Get current data sector */ + + if ( !sect ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + + sect += csect; + + if ( move_window( fp->fs, sect ) ) /* Move sector window */ + { + ABORT( fp->fs, FR_DISK_ERR ); + } + + fp->dsect = sect; + rcnt = SS( fp->fs ) - ( WORD )( fp->fptr % SS( fp->fs ) ); /* Forward data from sector window */ + + if ( rcnt > btr ) + { + rcnt = btr; + } + + rcnt = ( *func )( &fp->fs->win[( WORD )fp->fptr % SS( fp->fs )], rcnt ); + + if ( !rcnt ) + { + ABORT( fp->fs, FR_INT_ERR ); + } + } + + LEAVE_FF( fp->fs, FR_OK ); } #endif /* _USE_FORWARD */ @@ -3379,218 +5148,342 @@ FRESULT f_forward ( /*-----------------------------------------------------------------------*/ /* Create File System on the Drive */ /*-----------------------------------------------------------------------*/ -#define N_ROOTDIR 512 /* Multiple of 32 */ -#define N_FATS 1 /* 1 or 2 */ +#define N_ROOTDIR 512 /* Multiple of 32 */ +#define N_FATS 1 /* 1 or 2 */ FRESULT f_mkfs ( - BYTE drv, /* Logical drive number */ - BYTE sfd, /* Partitioning rule 0:FDISK, 1:SFD */ - UINT au /* Allocation unit size [bytes] */ + BYTE drv, /* Logical drive number */ + BYTE sfd, /* Partitioning rule 0:FDISK, 1:SFD */ + UINT au /* Allocation unit size [bytes] */ ) { - static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0}; - static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512}; - BYTE fmt, md, *tbl; - DWORD n_clst, vs, n, wsect; - UINT i; - DWORD b_vol, b_fat, b_dir, b_data; /* Offset (LBA) */ - DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */ - FATFS *fs; - DSTATUS stat; + static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0}; + static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512}; + BYTE fmt, md, *tbl; + DWORD n_clst, vs, n, wsect; + UINT i; + DWORD b_vol, b_fat, b_dir, b_data; /* Offset (LBA) */ + DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */ + FATFS *fs; + DSTATUS stat; - /* Check mounted drive and clear work area */ - if (drv >= _VOLUMES) return FR_INVALID_DRIVE; - fs = FatFs[drv]; - if (!fs) return FR_NOT_ENABLED; - fs->fs_type = 0; - drv = LD2PD(drv); + /* Check mounted drive and clear work area */ + if ( drv >= _VOLUMES ) + { + return FR_INVALID_DRIVE; + } - /* Get disk statics */ - stat = disk_initialize(drv); - if (stat & STA_NOINIT) return FR_NOT_READY; - if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; -#if _MAX_SS != 512 /* Get disk sector size */ - if (disk_ioctl(drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) - return FR_DISK_ERR; -#endif - if (disk_ioctl(drv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128) - return FR_DISK_ERR; - b_vol = (sfd) ? 0 : 63; /* Volume start sector */ - n_vol -= b_vol; - if (au & (au - 1)) au = 0; /* Check validity of the allocation unit size */ - if (!au) { /* AU auto selection */ - vs = n_vol / (2000 / (SS(fs) / 512)); - for (i = 0; vs < vst[i]; i++) ; - au = cst[i]; - } - au /= SS(fs); /* Number of sectors per cluster */ - if (au == 0) au = 1; - if (au > 128) au = 128; + fs = FatFs[drv]; - /* Pre-compute number of clusters and FAT syb-type */ - n_clst = n_vol / au; - fmt = FS_FAT12; - if (n_clst >= MIN_FAT16) fmt = FS_FAT16; - if (n_clst >= MIN_FAT32) fmt = FS_FAT32; + if ( !fs ) + { + return FR_NOT_ENABLED; + } - /* Determine offset and size of FAT structure */ - if (fmt == FS_FAT32) { - n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs); - n_rsv = 32; - n_dir = 0; - } else { - n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4; - n_fat = (n_fat + SS(fs) - 1) / SS(fs); - n_rsv = 1; - n_dir = N_ROOTDIR * 32UL / SS(fs); - } - b_fat = b_vol + n_rsv; /* FAT area start sector */ - b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */ - b_data = b_dir + n_dir; /* Data area start sector */ - if (n_vol < b_data + au) return FR_MKFS_ABORTED; /* Too small volume */ + fs->fs_type = 0; + drv = LD2PD( drv ); - /* Align data start sector to erase block boundary (for flash memory media) */ - if (disk_ioctl(drv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1; - n = (b_data + n - 1) & ~(n - 1); /* Next nearest erase block from current data start */ - n = (n - b_data) / N_FATS; - if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */ - n_rsv += n; - b_fat += n; - } else { /* FAT12/16: Expand FAT size */ - n_fat += n; - } + /* Get disk statics */ + stat = disk_initialize( drv ); - /* Determine number of cluster and final check of validity of the FAT sub-type */ - n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au; - if ( (fmt == FS_FAT16 && n_clst < MIN_FAT16) - || (fmt == FS_FAT32 && n_clst < MIN_FAT32)) - return FR_MKFS_ABORTED; + if ( stat & STA_NOINIT ) + { + return FR_NOT_READY; + } - /* Create partition table if required */ - if (sfd) { - md = 0xF0; - } else { - DWORD n_disk = b_vol + n_vol; + if ( stat & STA_PROTECT ) + { + return FR_WRITE_PROTECTED; + } - mem_set(fs->win, 0, SS(fs)); - tbl = fs->win+MBR_Table; - ST_DWORD(tbl, 0x00010180); /* Partition start in CHS */ - if (n_disk < 63UL * 255 * 1024) { /* Partition end in CHS */ - n_disk = n_disk / 63 / 255; - tbl[7] = (BYTE)n_disk; - tbl[6] = (BYTE)((n_disk >> 2) | 63); - } else { - ST_WORD(&tbl[6], 0xFFFF); - } - tbl[5] = 254; - if (fmt != FS_FAT32) /* System ID */ - tbl[4] = (n_vol < 0x10000) ? 0x04 : 0x06; - else - tbl[4] = 0x0c; - ST_DWORD(tbl+8, 63); /* Partition start in LBA */ - ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */ - ST_WORD(tbl+64, 0xAA55); /* Signature */ - if (disk_write(drv, fs->win, 0, 1) != RES_OK) - return FR_DISK_ERR; - md = 0xF8; - } +#if _MAX_SS != 512 /* Get disk sector size */ - /* Create volume boot record */ - tbl = fs->win; /* Clear sector */ - mem_set(tbl, 0, SS(fs)); - mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot code, OEM name */ - i = SS(fs); /* Sector size */ - ST_WORD(tbl+BPB_BytsPerSec, i); - tbl[BPB_SecPerClus] = (BYTE)au; /* Sectors per cluster */ - ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv); /* Reserved sectors */ - tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */ - i = (fmt == FS_FAT32) ? 0 : N_ROOTDIR; /* Number of rootdir entries */ - ST_WORD(tbl+BPB_RootEntCnt, i); - if (n_vol < 0x10000) { /* Number of total sectors */ - ST_WORD(tbl+BPB_TotSec16, n_vol); - } else { - ST_DWORD(tbl+BPB_TotSec32, n_vol); - } - tbl[BPB_Media] = md; /* Media descriptor */ - ST_WORD(tbl+BPB_SecPerTrk, 63); /* Number of sectors per track */ - ST_WORD(tbl+BPB_NumHeads, 255); /* Number of heads */ - ST_DWORD(tbl+BPB_HiddSec, b_vol); /* Hidden sectors */ - n = get_fattime(); /* Use current time as VSN */ - if (fmt == FS_FAT32) { - ST_DWORD(tbl+BS_VolID32, n); /* VSN */ - ST_DWORD(tbl+BPB_FATSz32, n_fat); /* Number of sectors per FAT */ - ST_DWORD(tbl+BPB_RootClus, 2); /* Root directory start cluster (2) */ - ST_WORD(tbl+BPB_FSInfo, 1); /* FSInfo record offset (VBR+1) */ - ST_WORD(tbl+BPB_BkBootSec, 6); /* Backup boot record offset (VBR+6) */ - tbl[BS_DrvNum32] = 0x80; /* Drive number */ - tbl[BS_BootSig32] = 0x29; /* Extended boot signature */ - mem_cpy(tbl+BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */ - } else { - ST_DWORD(tbl+BS_VolID, n); /* VSN */ - ST_WORD(tbl+BPB_FATSz16, n_fat); /* Number of sectors per FAT */ - tbl[BS_DrvNum] = 0x80; /* Drive number */ - tbl[BS_BootSig] = 0x29; /* Extended boot signature */ - mem_cpy(tbl+BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ - } - ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */ - if (disk_write(drv, tbl, b_vol, 1) != RES_OK)/* Write original (VBR) */ - return FR_DISK_ERR; - if (fmt == FS_FAT32) /* Write backup (VBR+6) */ - disk_write(drv, tbl, b_vol + 6, 1); + if ( disk_ioctl( drv, GET_SECTOR_SIZE, &SS( fs ) ) != RES_OK ) + { + return FR_DISK_ERR; + } - /* Initialize FAT area */ - wsect = b_fat; - for (i = 0; i < N_FATS; i++) { - mem_set(tbl, 0, SS(fs)); /* 1st sector of the FAT */ - n = md; /* Media descriptor byte */ - if (fmt != FS_FAT32) { - n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00; - ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT12/16) */ - } else { - n |= 0xFFFFFF00; - ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT32) */ - ST_DWORD(tbl+4, 0xFFFFFFFF); - ST_DWORD(tbl+8, 0x0FFFFFFF); /* Reserve cluster #2 for root dir */ - } - if (disk_write(drv, tbl, wsect++, 1) != RES_OK) - return FR_DISK_ERR; - mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */ - for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector write */ - if (disk_write(drv, tbl, wsect++, 1) != RES_OK) - return FR_DISK_ERR; - } - } - - /* Initialize root directory */ - i = (fmt == FS_FAT32) ? au : n_dir; - do { - if (disk_write(drv, tbl, wsect++, 1) != RES_OK) - return FR_DISK_ERR; - } while (--i); - -#if _USE_ERASE /* Erase data area if needed */ - { - DWORD eb[2]; - - eb[0] = wsect; eb[1] = wsect + n_clst * au - 1; - disk_ioctl(drv, CTRL_ERASE_SECTOR, eb); - } #endif - /* Create FSInfo if needed */ - if (fmt == FS_FAT32) { - ST_WORD(tbl+BS_55AA, 0xAA55); - ST_DWORD(tbl+FSI_LeadSig, 0x41615252); - ST_DWORD(tbl+FSI_StrucSig, 0x61417272); - ST_DWORD(tbl+FSI_Free_Count, n_clst - 1); - ST_DWORD(tbl+FSI_Nxt_Free, 0xFFFFFFFF); - disk_write(drv, tbl, b_vol + 1, 1); /* Write original (VBR+1) */ - disk_write(drv, tbl, b_vol + 7, 1); /* Write backup (VBR+7) */ - } + if ( disk_ioctl( drv, GET_SECTOR_COUNT, &n_vol ) != RES_OK || n_vol < 128 ) + { + return FR_DISK_ERR; + } - return (disk_ioctl(drv, CTRL_SYNC, (void*)0) == RES_OK) ? FR_OK : FR_DISK_ERR; + b_vol = ( sfd ) ? 0 : 63; /* Volume start sector */ + n_vol -= b_vol; + + if ( au & ( au - 1 ) ) + { + au = 0; /* Check validity of the allocation unit size */ + } + + if ( !au ) /* AU auto selection */ + { + vs = n_vol / ( 2000 / ( SS( fs ) / 512 ) ); + + for ( i = 0; vs < vst[i]; i++ ) ; + + au = cst[i]; + } + + au /= SS( fs ); /* Number of sectors per cluster */ + + if ( au == 0 ) + { + au = 1; + } + + if ( au > 128 ) + { + au = 128; + } + + /* Pre-compute number of clusters and FAT syb-type */ + n_clst = n_vol / au; + fmt = FS_FAT12; + + if ( n_clst >= MIN_FAT16 ) + { + fmt = FS_FAT16; + } + + if ( n_clst >= MIN_FAT32 ) + { + fmt = FS_FAT32; + } + + /* Determine offset and size of FAT structure */ + if ( fmt == FS_FAT32 ) + { + n_fat = ( ( n_clst * 4 ) + 8 + SS( fs ) - 1 ) / SS( fs ); + n_rsv = 32; + n_dir = 0; + } + else + { + n_fat = ( fmt == FS_FAT12 ) ? ( n_clst * 3 + 1 ) / 2 + 3 : ( n_clst * 2 ) + 4; + n_fat = ( n_fat + SS( fs ) - 1 ) / SS( fs ); + n_rsv = 1; + n_dir = N_ROOTDIR * 32UL / SS( fs ); + } + + b_fat = b_vol + n_rsv; /* FAT area start sector */ + b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */ + b_data = b_dir + n_dir; /* Data area start sector */ + + if ( n_vol < b_data + au ) + { + return FR_MKFS_ABORTED; /* Too small volume */ + } + + /* Align data start sector to erase block boundary (for flash memory media) */ + if ( disk_ioctl( drv, GET_BLOCK_SIZE, &n ) != RES_OK || !n || n > 32768 ) + { + n = 1; + } + + n = ( b_data + n - 1 ) & ~( n - 1 ); /* Next nearest erase block from current data start */ + n = ( n - b_data ) / N_FATS; + + if ( fmt == FS_FAT32 ) /* FAT32: Move FAT offset */ + { + n_rsv += n; + b_fat += n; + } + else /* FAT12/16: Expand FAT size */ + { + n_fat += n; + } + + /* Determine number of cluster and final check of validity of the FAT sub-type */ + n_clst = ( n_vol - n_rsv - n_fat * N_FATS - n_dir ) / au; + + if ( ( fmt == FS_FAT16 && n_clst < MIN_FAT16 ) + || ( fmt == FS_FAT32 && n_clst < MIN_FAT32 ) ) + { + return FR_MKFS_ABORTED; + } + + /* Create partition table if required */ + if ( sfd ) + { + md = 0xF0; + } + else + { + DWORD n_disk = b_vol + n_vol; + + mem_set( fs->win, 0, SS( fs ) ); + tbl = fs->win + MBR_Table; + ST_DWORD( tbl, 0x00010180 ); /* Partition start in CHS */ + + if ( n_disk < 63UL * 255 * 1024 ) /* Partition end in CHS */ + { + n_disk = n_disk / 63 / 255; + tbl[7] = ( BYTE )n_disk; + tbl[6] = ( BYTE )( ( n_disk >> 2 ) | 63 ); + } + else + { + ST_WORD( &tbl[6], 0xFFFF ); + } + + tbl[5] = 254; + + if ( fmt != FS_FAT32 ) /* System ID */ + { + tbl[4] = ( n_vol < 0x10000 ) ? 0x04 : 0x06; + } + else + { + tbl[4] = 0x0c; + } + + ST_DWORD( tbl + 8, 63 ); /* Partition start in LBA */ + ST_DWORD( tbl + 12, n_vol ); /* Partition size in LBA */ + ST_WORD( tbl + 64, 0xAA55 ); /* Signature */ + + if ( disk_write( drv, fs->win, 0, 1 ) != RES_OK ) + { + return FR_DISK_ERR; + } + + md = 0xF8; + } + + /* Create volume boot record */ + tbl = fs->win; /* Clear sector */ + mem_set( tbl, 0, SS( fs ) ); + mem_cpy( tbl, "\xEB\xFE\x90" "MSDOS5.0", 11 ); /* Boot code, OEM name */ + i = SS( fs ); /* Sector size */ + ST_WORD( tbl + BPB_BytsPerSec, i ); + tbl[BPB_SecPerClus] = ( BYTE )au; /* Sectors per cluster */ + ST_WORD( tbl + BPB_RsvdSecCnt, n_rsv ); /* Reserved sectors */ + tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */ + i = ( fmt == FS_FAT32 ) ? 0 : N_ROOTDIR; /* Number of rootdir entries */ + ST_WORD( tbl + BPB_RootEntCnt, i ); + + if ( n_vol < 0x10000 ) /* Number of total sectors */ + { + ST_WORD( tbl + BPB_TotSec16, n_vol ); + } + else + { + ST_DWORD( tbl + BPB_TotSec32, n_vol ); + } + + tbl[BPB_Media] = md; /* Media descriptor */ + ST_WORD( tbl + BPB_SecPerTrk, 63 ); /* Number of sectors per track */ + ST_WORD( tbl + BPB_NumHeads, 255 ); /* Number of heads */ + ST_DWORD( tbl + BPB_HiddSec, b_vol ); /* Hidden sectors */ + n = get_fattime(); /* Use current time as VSN */ + + if ( fmt == FS_FAT32 ) + { + ST_DWORD( tbl + BS_VolID32, n ); /* VSN */ + ST_DWORD( tbl + BPB_FATSz32, n_fat ); /* Number of sectors per FAT */ + ST_DWORD( tbl + BPB_RootClus, 2 ); /* Root directory start cluster (2) */ + ST_WORD( tbl + BPB_FSInfo, 1 ); /* FSInfo record offset (VBR+1) */ + ST_WORD( tbl + BPB_BkBootSec, 6 ); /* Backup boot record offset (VBR+6) */ + tbl[BS_DrvNum32] = 0x80; /* Drive number */ + tbl[BS_BootSig32] = 0x29; /* Extended boot signature */ + mem_cpy( tbl + BS_VolLab32, "NO NAME " "FAT32 ", 19 ); /* Volume label, FAT signature */ + } + else + { + ST_DWORD( tbl + BS_VolID, n ); /* VSN */ + ST_WORD( tbl + BPB_FATSz16, n_fat ); /* Number of sectors per FAT */ + tbl[BS_DrvNum] = 0x80; /* Drive number */ + tbl[BS_BootSig] = 0x29; /* Extended boot signature */ + mem_cpy( tbl + BS_VolLab, "NO NAME " "FAT ", 19 ); /* Volume label, FAT signature */ + } + + ST_WORD( tbl + BS_55AA, 0xAA55 ); /* Signature (Offset is fixed here regardless of sector size) */ + + if ( disk_write( drv, tbl, b_vol, 1 ) != RES_OK ) /* Write original (VBR) */ + { + return FR_DISK_ERR; + } + + if ( fmt == FS_FAT32 ) /* Write backup (VBR+6) */ + { + disk_write( drv, tbl, b_vol + 6, 1 ); + } + + /* Initialize FAT area */ + wsect = b_fat; + + for ( i = 0; i < N_FATS; i++ ) + { + mem_set( tbl, 0, SS( fs ) ); /* 1st sector of the FAT */ + n = md; /* Media descriptor byte */ + + if ( fmt != FS_FAT32 ) + { + n |= ( fmt == FS_FAT12 ) ? 0x00FFFF00 : 0xFFFFFF00; + ST_DWORD( tbl + 0, n ); /* Reserve cluster #0-1 (FAT12/16) */ + } + else + { + n |= 0xFFFFFF00; + ST_DWORD( tbl + 0, n ); /* Reserve cluster #0-1 (FAT32) */ + ST_DWORD( tbl + 4, 0xFFFFFFFF ); + ST_DWORD( tbl + 8, 0x0FFFFFFF ); /* Reserve cluster #2 for root dir */ + } + + if ( disk_write( drv, tbl, wsect++, 1 ) != RES_OK ) + { + return FR_DISK_ERR; + } + + mem_set( tbl, 0, SS( fs ) ); /* Fill following FAT entries with zero */ + + for ( n = 1; n < n_fat; n++ ) /* This loop may take a time on FAT32 volume due to many single sector write */ + { + if ( disk_write( drv, tbl, wsect++, 1 ) != RES_OK ) + { + return FR_DISK_ERR; + } + } + } + + /* Initialize root directory */ + i = ( fmt == FS_FAT32 ) ? au : n_dir; + + do + { + if ( disk_write( drv, tbl, wsect++, 1 ) != RES_OK ) + { + return FR_DISK_ERR; + } + } + while ( --i ); + +#if _USE_ERASE /* Erase data area if needed */ + { + DWORD eb[2]; + + eb[0] = wsect; eb[1] = wsect + n_clst * au - 1; + disk_ioctl( drv, CTRL_ERASE_SECTOR, eb ); + } +#endif + + /* Create FSInfo if needed */ + if ( fmt == FS_FAT32 ) + { + ST_WORD( tbl + BS_55AA, 0xAA55 ); + ST_DWORD( tbl + FSI_LeadSig, 0x41615252 ); + ST_DWORD( tbl + FSI_StrucSig, 0x61417272 ); + ST_DWORD( tbl + FSI_Free_Count, n_clst - 1 ); + ST_DWORD( tbl + FSI_Nxt_Free, 0xFFFFFFFF ); + disk_write( drv, tbl, b_vol + 1, 1 ); /* Write original (VBR+1) */ + disk_write( drv, tbl, b_vol + 7, 1 ); /* Write backup (VBR+7) */ + } + + return ( disk_ioctl( drv, CTRL_SYNC, ( void * )0 ) == RES_OK ) ? FR_OK : FR_DISK_ERR; } #endif /* _USE_MKFS && !_FS_READONLY */ @@ -3602,52 +5495,103 @@ FRESULT f_mkfs ( /*-----------------------------------------------------------------------*/ /* Get a string from the file */ /*-----------------------------------------------------------------------*/ -TCHAR* f_gets ( - TCHAR* buff, /* Pointer to the string buffer to read */ - int len, /* Size of string buffer (characters) */ - FIL* fil /* Pointer to the file object */ +TCHAR *f_gets ( + TCHAR *buff, /* Pointer to the string buffer to read */ + int len, /* Size of string buffer (characters) */ + FIL *fil /* Pointer to the file object */ ) { - int n = 0; - TCHAR c, *p = buff; - BYTE s[2]; - UINT rc; + int n = 0; + TCHAR c, *p = buff; + BYTE s[2]; + UINT rc; - while (n < len - 1) { /* Read bytes until buffer gets filled */ - f_read(fil, s, 1, &rc); - if (rc != 1) break; /* Break on EOF or error */ - c = s[0]; -#if _LFN_UNICODE /* Read a character in UTF-8 encoding */ - if (c >= 0x80) { - if (c < 0xC0) continue; /* Skip stray trailer */ - if (c < 0xE0) { /* Two-byte sequense */ - f_read(fil, s, 1, &rc); - if (rc != 1) break; - c = ((c & 0x1F) << 6) | (s[0] & 0x3F); - if (c < 0x80) c = '?'; - } else { - if (c < 0xF0) { /* Three-byte sequense */ - f_read(fil, s, 2, &rc); - if (rc != 2) break; - c = (c << 12) | ((s[0] & 0x3F) << 6) | (s[1] & 0x3F); - if (c < 0x800) c = '?'; - } else { /* Reject four-byte sequense */ - c = '?'; - } - } - } + while ( n < len - 1 ) /* Read bytes until buffer gets filled */ + { + f_read( fil, s, 1, &rc ); + + if ( rc != 1 ) + { + break; /* Break on EOF or error */ + } + + c = s[0]; +#if _LFN_UNICODE /* Read a character in UTF-8 encoding */ + + if ( c >= 0x80 ) + { + if ( c < 0xC0 ) + { + continue; /* Skip stray trailer */ + } + + if ( c < 0xE0 ) /* Two-byte sequense */ + { + f_read( fil, s, 1, &rc ); + + if ( rc != 1 ) + { + break; + } + + c = ( ( c & 0x1F ) << 6 ) | ( s[0] & 0x3F ); + + if ( c < 0x80 ) + { + c = '?'; + } + } + else + { + if ( c < 0xF0 ) /* Three-byte sequense */ + { + f_read( fil, s, 2, &rc ); + + if ( rc != 2 ) + { + break; + } + + c = ( c << 12 ) | ( ( s[0] & 0x3F ) << 6 ) | ( s[1] & 0x3F ); + + if ( c < 0x800 ) + { + c = '?'; + } + } + else /* Reject four-byte sequense */ + { + c = '?'; + } + } + } + #endif #if _USE_STRFUNC >= 2 - if (c == '\r') continue; /* Strip '\r' */ + + if ( c == '\r' ) + { + continue; /* Strip '\r' */ + } + #endif - *p++ = c; - n++; - if (c == '\n') break; /* Break on EOL */ - if (c == 0) break; /* Break on NUL */ - } - *p = 0; - return n ? buff : 0; /* When no data read (eof or error), return with error. */ + *p++ = c; + n++; + + if ( c == '\n' ) + { + break; /* Break on EOL */ + } + + if ( c == 0 ) + { + break; /* Break on NUL */ + } + } + + *p = 0; + return n ? buff : 0; /* When no data read (eof or error), return with error. */ } @@ -3658,40 +5602,53 @@ TCHAR* f_gets ( /* Put a character to the file */ /*-----------------------------------------------------------------------*/ int f_putc ( - TCHAR c, /* A character to be output */ - FIL* fil /* Pointer to the file object */ + TCHAR c, /* A character to be output */ + FIL *fil /* Pointer to the file object */ ) { - UINT bw, btw; - BYTE s[3]; + UINT bw, btw; + BYTE s[3]; #if _USE_STRFUNC >= 2 - if (c == '\n') f_putc ('\r', fil); /* LF -> CRLF conversion */ + + if ( c == '\n' ) + { + f_putc ( '\r', fil ); /* LF -> CRLF conversion */ + } + #endif -#if _LFN_UNICODE /* Write the character in UTF-8 encoding */ - if (c < 0x80) { /* 7-bit */ - s[0] = (BYTE)c; - btw = 1; - } else { - if (c < 0x800) { /* 11-bit */ - s[0] = (BYTE)(0xC0 | (c >> 6)); - s[1] = (BYTE)(0x80 | (c & 0x3F)); - btw = 2; - } else { /* 16-bit */ - s[0] = (BYTE)(0xE0 | (c >> 12)); - s[1] = (BYTE)(0x80 | ((c >> 6) & 0x3F)); - s[2] = (BYTE)(0x80 | (c & 0x3F)); - btw = 3; - } - } -#else /* Write the character without conversion */ - s[0] = (BYTE)c; - btw = 1; +#if _LFN_UNICODE /* Write the character in UTF-8 encoding */ + + if ( c < 0x80 ) /* 7-bit */ + { + s[0] = ( BYTE )c; + btw = 1; + } + else + { + if ( c < 0x800 ) /* 11-bit */ + { + s[0] = ( BYTE )( 0xC0 | ( c >> 6 ) ); + s[1] = ( BYTE )( 0x80 | ( c & 0x3F ) ); + btw = 2; + } + else /* 16-bit */ + { + s[0] = ( BYTE )( 0xE0 | ( c >> 12 ) ); + s[1] = ( BYTE )( 0x80 | ( ( c >> 6 ) & 0x3F ) ); + s[2] = ( BYTE )( 0x80 | ( c & 0x3F ) ); + btw = 3; + } + } + +#else /* Write the character without conversion */ + s[0] = ( BYTE )c; + btw = 1; #endif - f_write(fil, s, btw, &bw); /* Write the char to the file */ - return (bw == btw) ? 1 : EOF; /* Return the result */ + f_write( fil, s, btw, &bw ); /* Write the char to the file */ + return ( bw == btw ) ? 1 : EOF; /* Return the result */ } @@ -3701,17 +5658,22 @@ int f_putc ( /* Put a string to the file */ /*-----------------------------------------------------------------------*/ int f_puts ( - const TCHAR* str, /* Pointer to the string to be output */ - FIL* fil /* Pointer to the file object */ + const TCHAR *str, /* Pointer to the string to be output */ + FIL *fil /* Pointer to the file object */ ) { - int n; + int n; - for (n = 0; *str; str++, n++) { - if (f_putc(*str, fil) == EOF) return EOF; - } - return n; + for ( n = 0; *str; str++, n++ ) + { + if ( f_putc( *str, fil ) == EOF ) + { + return EOF; + } + } + + return n; } @@ -3721,93 +5683,156 @@ int f_puts ( /* Put a formatted string to the file */ /*-----------------------------------------------------------------------*/ int f_printf ( - FIL* fil, /* Pointer to the file object */ - const TCHAR* str, /* Pointer to the format string */ - ... /* Optional arguments... */ + FIL *fil, /* Pointer to the file object */ + const TCHAR *str, /* Pointer to the format string */ + ... /* Optional arguments... */ ) { - va_list arp; - BYTE f, r; - UINT i, w; - ULONG val; - TCHAR c, d, s[16]; - int res, cc; + va_list arp; + BYTE f, r; + UINT i, w; + ULONG val; + TCHAR c, d, s[16]; + int res, cc; - va_start(arp, str); + va_start( arp, str ); - for (cc = res = 0; cc != EOF; res += cc) { - c = *str++; - if (c == 0) break; /* End of string */ - if (c != '%') { /* Non escape character */ - cc = f_putc(c, fil); - if (cc != EOF) cc = 1; - continue; - } - w = f = 0; - c = *str++; - if (c == '0') { /* Flag: '0' padding */ - f = 1; c = *str++; - } - while (IsDigit(c)) { /* Precision */ - w = w * 10 + c - '0'; - c = *str++; - } - if (c == 'l' || c == 'L') { /* Prefix: Size is long int */ - f |= 2; c = *str++; - } - if (!c) break; - d = c; - if (IsLower(d)) d -= 0x20; - switch (d) { /* Type is... */ - case 'S' : /* String */ - cc = f_puts(va_arg(arp, TCHAR*), fil); continue; - case 'C' : /* Character */ - cc = f_putc((TCHAR)va_arg(arp, int), fil); continue; - case 'B' : /* Binary */ - r = 2; break; - case 'O' : /* Octal */ - r = 8; break; - case 'D' : /* Signed decimal */ - case 'U' : /* Unsigned decimal */ - r = 10; break; - case 'X' : /* Hexdecimal */ - r = 16; break; - default: /* Unknown */ - cc = f_putc(c, fil); continue; - } + for ( cc = res = 0; cc != EOF; res += cc ) + { + c = *str++; - /* Get an argument */ - val = (f & 2) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : va_arg(arp, unsigned int)); - if (d == 'D' && (val & 0x80000000)) { - val = 0 - val; - f |= 4; - } - /* Put it in numeral string */ - i = 0; - do { - d = (TCHAR)(val % r); val /= r; - if (d > 9) { - d += 7; - if (c == 'x') d += 0x20; - } - s[i++] = d + '0'; - } while (val && i < sizeof(s) / sizeof(s[0])); - if (f & 4) s[i++] = '-'; - cc = 0; - while (i < w-- && cc != EOF) { - cc = f_putc((TCHAR)((f & 1) ? '0' : ' '), fil); - res++; - } - do { - cc = f_putc(s[--i], fil); - res++; - } while (i && cc != EOF); - if (cc != EOF) cc = 0; - } + if ( c == 0 ) + { + break; /* End of string */ + } - va_end(arp); - return (cc == EOF) ? cc : res; + if ( c != '%' ) /* Non escape character */ + { + cc = f_putc( c, fil ); + + if ( cc != EOF ) + { + cc = 1; + } + + continue; + } + + w = f = 0; + c = *str++; + + if ( c == '0' ) /* Flag: '0' padding */ + { + f = 1; c = *str++; + } + + while ( IsDigit( c ) ) /* Precision */ + { + w = w * 10 + c - '0'; + c = *str++; + } + + if ( c == 'l' || c == 'L' ) /* Prefix: Size is long int */ + { + f |= 2; c = *str++; + } + + if ( !c ) + { + break; + } + + d = c; + + if ( IsLower( d ) ) + { + d -= 0x20; + } + + switch ( d ) /* Type is... */ + { + case 'S' : /* String */ + cc = f_puts( va_arg( arp, TCHAR * ), fil ); continue; + + case 'C' : /* Character */ + cc = f_putc( ( TCHAR )va_arg( arp, int ), fil ); continue; + + case 'B' : /* Binary */ + r = 2; break; + + case 'O' : /* Octal */ + r = 8; break; + + case 'D' : /* Signed decimal */ + case 'U' : /* Unsigned decimal */ + r = 10; break; + + case 'X' : /* Hexdecimal */ + r = 16; break; + + default: /* Unknown */ + cc = f_putc( c, fil ); continue; + } + + /* Get an argument */ + val = ( f & 2 ) ? va_arg( arp, long ) : ( ( d == 'D' ) ? ( long )va_arg( arp, int ) : va_arg( arp, unsigned int ) ); + + if ( d == 'D' && ( val & 0x80000000 ) ) + { + val = 0 - val; + f |= 4; + } + + /* Put it in numeral string */ + i = 0; + + do + { + d = ( TCHAR )( val % r ); val /= r; + + if ( d > 9 ) + { + d += 7; + + if ( c == 'x' ) + { + d += 0x20; + } + } + + s[i++] = d + '0'; + } + while ( val && i < sizeof( s ) / sizeof( s[0] ) ); + + if ( f & 4 ) + { + s[i++] = '-'; + } + + cc = 0; + + while ( i < w-- && cc != EOF ) + { + cc = f_putc( ( TCHAR )( ( f & 1 ) ? '0' : ' ' ), fil ); + res++; + } + + do + { + cc = f_putc( s[--i], fil ); + res++; + } + while ( i && cc != EOF ); + + if ( cc != EOF ) + { + cc = 0; + } + } + + va_end( arp ); + return ( cc == EOF ) ? cc : res; } #endif /* !_FS_READONLY */ diff --git a/src/ff.h b/src/ff.h index 55abce9..e1eb37c 100644 --- a/src/ff.h +++ b/src/ff.h @@ -15,14 +15,14 @@ /----------------------------------------------------------------------------*/ #ifndef _FATFS -#define _FATFS 8255 /* Revision ID */ +#define _FATFS 8255 /* Revision ID */ #ifdef __cplusplus extern "C" { #endif -#include "integer.h" /* Basic integer types */ -#include "ffconf.h" /* FatFs configuration options */ +#include "integer.h" /* Basic integer types */ +#include "ffconf.h" /* FatFs configuration options */ #if _FATFS != _FFCONF #error Wrong configuration file (ffconf.h). @@ -31,191 +31,191 @@ extern "C" { /* DBCS code ranges and SBCS extend char conversion table */ -#if _CODE_PAGE == 932 /* Japanese Shift-JIS */ -#define _DF1S 0x81 /* DBC 1st byte range 1 start */ -#define _DF1E 0x9F /* DBC 1st byte range 1 end */ -#define _DF2S 0xE0 /* DBC 1st byte range 2 start */ -#define _DF2E 0xFC /* DBC 1st byte range 2 end */ -#define _DS1S 0x40 /* DBC 2nd byte range 1 start */ -#define _DS1E 0x7E /* DBC 2nd byte range 1 end */ -#define _DS2S 0x80 /* DBC 2nd byte range 2 start */ -#define _DS2E 0xFC /* DBC 2nd byte range 2 end */ +#if _CODE_PAGE == 932 /* Japanese Shift-JIS */ +#define _DF1S 0x81 /* DBC 1st byte range 1 start */ +#define _DF1E 0x9F /* DBC 1st byte range 1 end */ +#define _DF2S 0xE0 /* DBC 1st byte range 2 start */ +#define _DF2E 0xFC /* DBC 1st byte range 2 end */ +#define _DS1S 0x40 /* DBC 2nd byte range 1 start */ +#define _DS1E 0x7E /* DBC 2nd byte range 1 end */ +#define _DS2S 0x80 /* DBC 2nd byte range 2 start */ +#define _DS2E 0xFC /* DBC 2nd byte range 2 end */ -#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */ -#define _DF1S 0x81 -#define _DF1E 0xFE -#define _DS1S 0x40 -#define _DS1E 0x7E -#define _DS2S 0x80 -#define _DS2E 0xFE +#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x40 +#define _DS1E 0x7E +#define _DS2S 0x80 +#define _DS2E 0xFE -#elif _CODE_PAGE == 949 /* Korean */ -#define _DF1S 0x81 -#define _DF1E 0xFE -#define _DS1S 0x41 -#define _DS1E 0x5A -#define _DS2S 0x61 -#define _DS2E 0x7A -#define _DS3S 0x81 -#define _DS3E 0xFE +#elif _CODE_PAGE == 949 /* Korean */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x41 +#define _DS1E 0x5A +#define _DS2S 0x61 +#define _DS2E 0x7A +#define _DS3S 0x81 +#define _DS3E 0xFE -#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */ -#define _DF1S 0x81 -#define _DF1E 0xFE -#define _DS1S 0x40 -#define _DS1E 0x7E -#define _DS2S 0xA1 -#define _DS2E 0xFE +#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x40 +#define _DS1E 0x7E +#define _DS2S 0xA1 +#define _DS2E 0xFE -#elif _CODE_PAGE == 437 /* U.S. (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 437 /* U.S. (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 720 /* Arabic (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 720 /* Arabic (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 737 /* Greek (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 737 /* Greek (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ - 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 775 /* Baltic (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 775 /* Baltic (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \ - 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} + 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} -#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */ +#define _DF1S 0 #define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ - 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ - 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} + 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ + 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 857 /* Turkish (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 857 /* Turkish (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ - 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 862 /* Hebrew (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 862 /* Hebrew (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 866 /* Russian (OEM) */ -#define _DF1S 0 +#elif _CODE_PAGE == 866 /* Russian (OEM) */ +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */ -#define _DF1S 0 +#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */ +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} #elif _CODE_PAGE == 1250 /* Central Europe (Windows) */ -#define _DF1S 0 +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} #elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */ -#define _DF1S 0 +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ - 0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF} + 0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF} #elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */ -#define _DF1S 0 +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} #elif _CODE_PAGE == 1253 /* Greek (Windows) */ -#define _DF1S 0 +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \ - 0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF} + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \ + 0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF} #elif _CODE_PAGE == 1254 /* Turkish (Windows) */ -#define _DF1S 0 +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} #elif _CODE_PAGE == 1255 /* Hebrew (Windows) */ -#define _DF1S 0 +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} #elif _CODE_PAGE == 1256 /* Arabic (Windows) */ -#define _DF1S 0 +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF} + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF} #elif _CODE_PAGE == 1257 /* Baltic (Windows) */ -#define _DF1S 0 +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} #elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */ -#define _DF1S 0 +#define _DF1S 0 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F} + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F} -#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */ -#define _DF1S 0 +#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */ +#define _DF1S 0 #else #error Unknown code page @@ -226,18 +226,19 @@ extern "C" { /* Definitions of volume management */ -#if _MULTI_PARTITION /* Multiple partition configuration */ -#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive# */ -#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition# */ -typedef struct { - BYTE pd; /* Physical drive# */ - BYTE pt; /* Partition # (0-3) */ +#if _MULTI_PARTITION /* Multiple partition configuration */ +#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive# */ +#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition# */ +typedef struct +{ + BYTE pd; /* Physical drive# */ + BYTE pt; /* Partition # (0-3) */ } PARTITION; -extern const PARTITION VolToPart[]; /* Volume - Physical location resolution table */ +extern const PARTITION VolToPart[]; /* Volume - Physical location resolution table */ -#else /* Single partition configuration */ -#define LD2PD(vol) (vol) /* Logical drive# is bound to the same physical drive# */ -#define LD2PT(vol) 0 /* Always mounts the 1st partition */ +#else /* Single partition configuration */ +#define LD2PD(vol) (vol) /* Logical drive# is bound to the same physical drive# */ +#define LD2PT(vol) 0 /* Always mounts the 1st partition */ #endif @@ -245,7 +246,7 @@ extern const PARTITION VolToPart[]; /* Volume - Physical location resolution tab /* Type of path name strings on FatFs API */ -#if _LFN_UNICODE /* Unicode string */ +#if _LFN_UNICODE /* Unicode string */ #if !_USE_LFN #error _LFN_UNICODE must be 0 in non-LFN cfg. #endif @@ -255,7 +256,7 @@ typedef WCHAR TCHAR; #define _TEXT(x) L ## x #endif -#else /* ANSI/OEM string */ +#else /* ANSI/OEM string */ #ifndef _INC_TCHAR typedef char TCHAR; #define _T(x) x @@ -268,64 +269,66 @@ typedef char TCHAR; /* File system object structure (FATFS) */ -typedef struct { - BYTE fs_type; /* FAT sub-type (0:Not mounted) */ - BYTE drv; /* Physical drive number */ - BYTE csize; /* Sectors per cluster (1,2,4...128) */ - BYTE n_fats; /* Number of FAT copies (1,2) */ - BYTE wflag; /* win[] dirty flag (1:must be written back) */ - BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */ - WORD id; /* File system mount ID */ - WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ +typedef struct +{ + BYTE fs_type; /* FAT sub-type (0:Not mounted) */ + BYTE drv; /* Physical drive number */ + BYTE csize; /* Sectors per cluster (1,2,4...128) */ + BYTE n_fats; /* Number of FAT copies (1,2) */ + BYTE wflag; /* win[] dirty flag (1:must be written back) */ + BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */ + WORD id; /* File system mount ID */ + WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ #if _MAX_SS != 512 - WORD ssize; /* Bytes per sector (512,1024,2048,4096) */ + WORD ssize; /* Bytes per sector (512,1024,2048,4096) */ #endif #if _FS_REENTRANT - _SYNC_t sobj; /* Identifier of sync object */ + _SYNC_t sobj; /* Identifier of sync object */ #endif #if !_FS_READONLY - DWORD last_clust; /* Last allocated cluster */ - DWORD free_clust; /* Number of free clusters */ - DWORD fsi_sector; /* fsinfo sector (FAT32) */ + DWORD last_clust; /* Last allocated cluster */ + DWORD free_clust; /* Number of free clusters */ + DWORD fsi_sector; /* fsinfo sector (FAT32) */ #endif #if _FS_RPATH - DWORD cdir; /* Current directory start cluster (0:root) */ + DWORD cdir; /* Current directory start cluster (0:root) */ #endif - DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */ - DWORD fsize; /* Sectors per FAT */ - DWORD fatbase; /* FAT start sector */ - DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */ - DWORD database; /* Data start sector */ - DWORD winsect; /* Current sector appearing in the win[] */ - BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */ + DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */ + DWORD fsize; /* Sectors per FAT */ + DWORD fatbase; /* FAT start sector */ + DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */ + DWORD database; /* Data start sector */ + DWORD winsect; /* Current sector appearing in the win[] */ + BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */ } FATFS; /* File object structure (FIL) */ -typedef struct { - FATFS* fs; /* Pointer to the owner file system object */ - WORD id; /* Owner file system mount ID */ - BYTE flag; /* File status flags */ - BYTE pad1; - DWORD fptr; /* File read/write pointer (0 on file open) */ - DWORD fsize; /* File size */ - DWORD org_clust; /* File start cluster (0 when fsize==0) */ - DWORD curr_clust; /* Current cluster */ - DWORD dsect; /* Current data sector */ +typedef struct +{ + FATFS *fs; /* Pointer to the owner file system object */ + WORD id; /* Owner file system mount ID */ + BYTE flag; /* File status flags */ + BYTE pad1; + DWORD fptr; /* File read/write pointer (0 on file open) */ + DWORD fsize; /* File size */ + DWORD org_clust; /* File start cluster (0 when fsize==0) */ + DWORD curr_clust; /* Current cluster */ + DWORD dsect; /* Current data sector */ #if !_FS_READONLY - DWORD dir_sect; /* Sector containing the directory entry */ - BYTE* dir_ptr; /* Ponter to the directory entry in the window */ + DWORD dir_sect; /* Sector containing the directory entry */ + BYTE *dir_ptr; /* Ponter to the directory entry in the window */ #endif #if _USE_FASTSEEK - DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */ + DWORD *cltbl; /* Pointer to the cluster link map table (null on file open) */ #endif #if _FS_SHARE - UINT lockid; /* File lock ID (index of file semaphore table) */ + UINT lockid; /* File lock ID (index of file semaphore table) */ #endif #if !_FS_TINY - BYTE buf[_MAX_SS]; /* File data read/write buffer */ + BYTE buf[_MAX_SS]; /* File data read/write buffer */ #endif } FIL; @@ -333,18 +336,19 @@ typedef struct { /* Directory object structure (DIR) */ -typedef struct { - FATFS* fs; /* Pointer to the owner file system object */ - WORD id; /* Owner file system mount ID */ - WORD index; /* Current read/write index number */ - DWORD sclust; /* Table start cluster (0:Root dir) */ - DWORD clust; /* Current cluster */ - DWORD sect; /* Current sector */ - BYTE* dir; /* Pointer to the current SFN entry in the win[] */ - BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */ +typedef struct +{ + FATFS *fs; /* Pointer to the owner file system object */ + WORD id; /* Owner file system mount ID */ + WORD index; /* Current read/write index number */ + DWORD sclust; /* Table start cluster (0:Root dir) */ + DWORD clust; /* Current cluster */ + DWORD sect; /* Current sector */ + BYTE *dir; /* Pointer to the current SFN entry in the win[] */ + BYTE *fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */ #if _USE_LFN - WCHAR* lfn; /* Pointer to the LFN working buffer */ - WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */ + WCHAR *lfn; /* Pointer to the LFN working buffer */ + WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */ #endif } DIR; @@ -352,16 +356,17 @@ typedef struct { /* File status structure (FILINFO) */ -typedef struct { - DWORD fsize; /* File size */ - WORD fdate; /* Last modified date */ - WORD ftime; /* Last modified time */ - BYTE fattrib; /* Attribute */ - TCHAR fname[13]; /* Short file name (8.3 format) */ - DWORD clust; /* start cluster */ +typedef struct +{ + DWORD fsize; /* File size */ + WORD fdate; /* Last modified date */ + WORD ftime; /* Last modified time */ + BYTE fattrib; /* Attribute */ + TCHAR fname[13]; /* Short file name (8.3 format) */ + DWORD clust; /* start cluster */ #if _USE_LFN - TCHAR* lfname; /* Pointer to the LFN buffer */ - UINT lfsize; /* Size of LFN buffer in TCHAR */ + TCHAR *lfname; /* Pointer to the LFN buffer */ + UINT lfsize; /* Size of LFN buffer in TCHAR */ #endif } FILINFO; @@ -369,26 +374,27 @@ typedef struct { /* File function return code (FRESULT) */ -typedef enum { - FR_OK = 0, /* (0) Succeeded */ - FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */ - FR_INT_ERR, /* (2) Assertion failed */ - FR_NOT_READY, /* (3) The physical drive cannot work */ - FR_NO_FILE, /* (4) Could not find the file */ - FR_NO_PATH, /* (5) Could not find the path */ - FR_INVALID_NAME, /* (6) The path name format is invalid */ - FR_DENIED, /* (7) Acces denied due to prohibited access or directory full */ - FR_EXIST, /* (8) Acces denied due to prohibited access */ - FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ - FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ - FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ - FR_NOT_ENABLED, /* (12) The volume has no work area */ - FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume on the physical drive */ - FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ - FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ - FR_LOCKED, /* (16) The operation is rejected according to the file shareing policy */ - FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ - FR_TOO_MANY_OPEN_FILES /* (18) Number of open files > _FS_SHARE */ +typedef enum +{ + FR_OK = 0, /* (0) Succeeded */ + FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */ + FR_INT_ERR, /* (2) Assertion failed */ + FR_NOT_READY, /* (3) The physical drive cannot work */ + FR_NO_FILE, /* (4) Could not find the file */ + FR_NO_PATH, /* (5) Could not find the path */ + FR_INVALID_NAME, /* (6) The path name format is invalid */ + FR_DENIED, /* (7) Acces denied due to prohibited access or directory full */ + FR_EXIST, /* (8) Acces denied due to prohibited access */ + FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ + FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ + FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ + FR_NOT_ENABLED, /* (12) The volume has no work area */ + FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume on the physical drive */ + FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ + FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ + FR_LOCKED, /* (16) The operation is rejected according to the file shareing policy */ + FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ + FR_TOO_MANY_OPEN_FILES /* (18) Number of open files > _FS_SHARE */ } FRESULT; @@ -397,50 +403,51 @@ typedef enum { /* FatFs module application interface */ /* Low Level functions */ -FRESULT l_openfilebycluster(FATFS *fs, FIL *fp, const TCHAR *path, DWORD clust, DWORD fsize); /* Open a file by its start cluster using supplied file size */ -FRESULT l_opendirbycluster (FATFS *fs, DIR *dj, const TCHAR *path, DWORD clust); +FRESULT l_openfilebycluster( FATFS *fs, FIL *fp, const TCHAR *path, DWORD clust, + DWORD fsize ); /* Open a file by its start cluster using supplied file size */ +FRESULT l_opendirbycluster ( FATFS *fs, DIR *dj, const TCHAR *path, DWORD clust ); /* application level functions */ -FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */ -FRESULT f_open (FIL*, const TCHAR*, BYTE); /* Open or create a file */ -FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */ -FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */ -FRESULT f_close (FIL*); /* Close an open file object */ -FRESULT f_opendir (DIR*, const TCHAR*); /* Open an existing directory */ -FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */ -FRESULT f_stat (const TCHAR*, FILINFO*); /* Get file status */ +FRESULT f_mount ( BYTE, FATFS * ); /* Mount/Unmount a logical drive */ +FRESULT f_open ( FIL *, const TCHAR *, BYTE ); /* Open or create a file */ +FRESULT f_read ( FIL *, void *, UINT, UINT * ); /* Read data from a file */ +FRESULT f_lseek ( FIL *, DWORD ); /* Move file pointer of a file object */ +FRESULT f_close ( FIL * ); /* Close an open file object */ +FRESULT f_opendir ( DIR *, const TCHAR * ); /* Open an existing directory */ +FRESULT f_readdir ( DIR *, FILINFO * ); /* Read a directory item */ +FRESULT f_stat ( const TCHAR *, FILINFO * ); /* Get file status */ #if !_FS_READONLY -FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */ -FRESULT f_getfree (const TCHAR*, DWORD*, FATFS**); /* Get number of free clusters on the drive */ -FRESULT f_truncate (FIL*); /* Truncate file */ -FRESULT f_sync (FIL*); /* Flush cached data of a writing file */ -FRESULT f_unlink (const TCHAR*); /* Delete an existing file or directory */ -FRESULT f_mkdir (const TCHAR*); /* Create a new directory */ -FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attriburte of the file/dir */ -FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change timestamp of the file/dir */ -FRESULT f_rename (const TCHAR*, const TCHAR*); /* Rename/Move a file or directory */ +FRESULT f_write ( FIL *, const void *, UINT, UINT * ); /* Write data to a file */ +FRESULT f_getfree ( const TCHAR *, DWORD *, FATFS ** ); /* Get number of free clusters on the drive */ +FRESULT f_truncate ( FIL * ); /* Truncate file */ +FRESULT f_sync ( FIL * ); /* Flush cached data of a writing file */ +FRESULT f_unlink ( const TCHAR * ); /* Delete an existing file or directory */ +FRESULT f_mkdir ( const TCHAR * ); /* Create a new directory */ +FRESULT f_chmod ( const TCHAR *, BYTE, BYTE ); /* Change attriburte of the file/dir */ +FRESULT f_utime ( const TCHAR *, const FILINFO * ); /* Change timestamp of the file/dir */ +FRESULT f_rename ( const TCHAR *, const TCHAR * ); /* Rename/Move a file or directory */ #endif #if _USE_FORWARD -FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */ +FRESULT f_forward ( FIL *, UINT( * )( const BYTE *, UINT ), UINT, UINT * ); /* Forward data to the stream */ #endif #if _USE_MKFS -FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */ +FRESULT f_mkfs ( BYTE, BYTE, UINT ); /* Create a file system on the drive */ #endif #if _FS_RPATH -FRESULT f_chdrive (BYTE); /* Change current drive */ -FRESULT f_chdir (const TCHAR*); /* Change current directory */ -FRESULT f_getcwd (TCHAR*, UINT); /* Get current directory */ +FRESULT f_chdrive ( BYTE ); /* Change current drive */ +FRESULT f_chdir ( const TCHAR * ); /* Change current directory */ +FRESULT f_getcwd ( TCHAR *, UINT ); /* Get current directory */ #endif #if _USE_STRFUNC -int f_putc (TCHAR, FIL*); /* Put a character to the file */ -int f_puts (const TCHAR*, FIL*); /* Put a string to the file */ -int f_printf (FIL*, const TCHAR*, ...); /* Put a formatted string to the file */ -TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */ +int f_putc ( TCHAR, FIL * ); /* Put a character to the file */ +int f_puts ( const TCHAR *, FIL * ); /* Put a string to the file */ +int f_printf ( FIL *, const TCHAR *, ... ); /* Put a formatted string to the file */ +TCHAR *f_gets ( TCHAR *, int, FIL * ); /* Get a string from the file */ #ifndef EOF #define EOF (-1) #endif @@ -458,25 +465,25 @@ TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */ /* RTC function */ #if !_FS_READONLY -DWORD get_fattime (void); +DWORD get_fattime ( void ); #endif /* Unicode support functions */ -#if _USE_LFN /* Unicode - OEM code conversion */ -WCHAR ff_convert (WCHAR, UINT); /* OEM-Unicode bidirectional conversion */ -WCHAR ff_wtoupper (WCHAR); /* Unicode upper-case conversion */ -#if _USE_LFN == 3 /* Memory functions */ -void* ff_memalloc (UINT); /* Allocate memory block */ -void ff_memfree (void*); /* Free memory block */ +#if _USE_LFN /* Unicode - OEM code conversion */ +WCHAR ff_convert ( WCHAR, UINT ); /* OEM-Unicode bidirectional conversion */ +WCHAR ff_wtoupper ( WCHAR ); /* Unicode upper-case conversion */ +#if _USE_LFN == 3 /* Memory functions */ +void *ff_memalloc ( UINT ); /* Allocate memory block */ +void ff_memfree ( void * ); /* Free memory block */ #endif #endif /* Sync functions */ #if _FS_REENTRANT -int ff_cre_syncobj (BYTE, _SYNC_t*);/* Create a sync object */ -int ff_del_syncobj (_SYNC_t); /* Delete a sync object */ -int ff_req_grant (_SYNC_t); /* Lock sync object */ -void ff_rel_grant (_SYNC_t); /* Unlock sync object */ +int ff_cre_syncobj ( BYTE, _SYNC_t * ); /* Create a sync object */ +int ff_del_syncobj ( _SYNC_t ); /* Delete a sync object */ +int ff_req_grant ( _SYNC_t ); /* Lock sync object */ +void ff_rel_grant ( _SYNC_t ); /* Unlock sync object */ #endif @@ -488,56 +495,56 @@ void ff_rel_grant (_SYNC_t); /* Unlock sync object */ /* File access control and file status flags (FIL.flag) */ -#define FA_READ 0x01 -#define FA_OPEN_EXISTING 0x00 -#define FA__ERROR 0x80 +#define FA_READ 0x01 +#define FA_OPEN_EXISTING 0x00 +#define FA__ERROR 0x80 #if !_FS_READONLY -#define FA_WRITE 0x02 -#define FA_CREATE_NEW 0x04 -#define FA_CREATE_ALWAYS 0x08 -#define FA_OPEN_ALWAYS 0x10 -#define FA__WRITTEN 0x20 -#define FA__DIRTY 0x40 +#define FA_WRITE 0x02 +#define FA_CREATE_NEW 0x04 +#define FA_CREATE_ALWAYS 0x08 +#define FA_OPEN_ALWAYS 0x10 +#define FA__WRITTEN 0x20 +#define FA__DIRTY 0x40 #endif /* FAT sub type (FATFS.fs_type) */ -#define FS_FAT12 1 -#define FS_FAT16 2 -#define FS_FAT32 3 +#define FS_FAT12 1 +#define FS_FAT16 2 +#define FS_FAT32 3 /* File attribute bits for directory entry */ -#define AM_RDO 0x01 /* Read only */ -#define AM_HID 0x02 /* Hidden */ -#define AM_SYS 0x04 /* System */ -#define AM_VOL 0x08 /* Volume label */ -#define AM_LFN 0x0F /* LFN entry */ -#define AM_DIR 0x10 /* Directory */ -#define AM_ARC 0x20 /* Archive */ -#define AM_MASK 0x3F /* Mask of defined bits */ +#define AM_RDO 0x01 /* Read only */ +#define AM_HID 0x02 /* Hidden */ +#define AM_SYS 0x04 /* System */ +#define AM_VOL 0x08 /* Volume label */ +#define AM_LFN 0x0F /* LFN entry */ +#define AM_DIR 0x10 /* Directory */ +#define AM_ARC 0x20 /* Archive */ +#define AM_MASK 0x3F /* Mask of defined bits */ /* Fast seek function */ -#define CREATE_LINKMAP 0xFFFFFFFF +#define CREATE_LINKMAP 0xFFFFFFFF /*--------------------------------*/ /* Multi-byte word access macros */ -#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */ -#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr)) -#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr)) -#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val) -#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val) -#else /* Use byte-by-byte access to the FAT structure */ -#define LD_WORD(ptr) (WORD)(((WORD)*(BYTE*)((ptr)+1)<<8)|(WORD)*(BYTE*)(ptr)) -#define LD_DWORD(ptr) (DWORD)(((DWORD)*(BYTE*)((ptr)+3)<<24)|((DWORD)*(BYTE*)((ptr)+2)<<16)|((WORD)*(BYTE*)((ptr)+1)<<8)|*(BYTE*)(ptr)) -#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8) -#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24) +#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */ +#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr)) +#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr)) +#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val) +#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val) +#else /* Use byte-by-byte access to the FAT structure */ +#define LD_WORD(ptr) (WORD)(((WORD)*(BYTE*)((ptr)+1)<<8)|(WORD)*(BYTE*)(ptr)) +#define LD_DWORD(ptr) (DWORD)(((DWORD)*(BYTE*)((ptr)+3)<<24)|((DWORD)*(BYTE*)((ptr)+2)<<16)|((WORD)*(BYTE*)((ptr)+1)<<8)|*(BYTE*)(ptr)) +#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8) +#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24) #endif #ifdef __cplusplus diff --git a/src/ffconf.h b/src/ffconf.h index b909757..baa0bd3 100644 --- a/src/ffconf.h +++ b/src/ffconf.h @@ -7,26 +7,26 @@ / /----------------------------------------------------------------------------*/ #ifndef _FFCONF -#define _FFCONF 8255 /* Revision ID */ +#define _FFCONF 8255 /* Revision ID */ /*---------------------------------------------------------------------------/ / Function and Buffer Configurations /----------------------------------------------------------------------------*/ -#define _FS_TINY 0 /* 0:Normal or 1:Tiny */ +#define _FS_TINY 0 /* 0:Normal or 1:Tiny */ /* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system / object instead of the sector buffer in the individual file object for file / data transfer. This reduces memory consumption 512 bytes each file object. */ -#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */ +#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */ /* Setting _FS_READONLY to 1 defines read only configuration. This removes / writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename, / f_truncate and useless f_getfree. */ -#define _FS_MINIMIZE 0 /* 0 to 3 */ +#define _FS_MINIMIZE 0 /* 0 to 3 */ /* The _FS_MINIMIZE option defines minimization level to remove some functions. / / 0: Full function. @@ -36,19 +36,19 @@ / 3: f_lseek is removed in addition to 2. */ -#define _USE_STRFUNC 1 /* 0:Disable or 1/2:Enable */ +#define _USE_STRFUNC 1 /* 0:Disable or 1/2:Enable */ /* To enable string functions, set _USE_STRFUNC to 1 or 2. */ -#define _USE_MKFS 0 /* 0:Disable or 1:Enable */ +#define _USE_MKFS 0 /* 0:Disable or 1:Enable */ /* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */ -#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */ +#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */ /* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */ -#define _USE_FASTSEEK 1 /* 0:Disable or 1:Enable */ +#define _USE_FASTSEEK 1 /* 0:Disable or 1:Enable */ /* To enable fast seek feature, set _USE_FASTSEEK to 1. */ @@ -57,7 +57,7 @@ / Locale and Namespace Configurations /----------------------------------------------------------------------------*/ -#define _CODE_PAGE 1252 +#define _CODE_PAGE 1252 /* The _CODE_PAGE specifies the OEM code page to be used on the target system. / Incorrect setting of the code page can cause a file open failure. / @@ -86,12 +86,12 @@ / 857 - Turkish (OEM) / 862 - Hebrew (OEM) / 874 - Thai (OEM, Windows) -/ 1 - ASCII only (Valid for non LFN cfg.) +/ 1 - ASCII only (Valid for non LFN cfg.) */ -#define _USE_LFN 1 /* 0 to 3 */ -#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */ +#define _USE_LFN 1 /* 0 to 3 */ +#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */ /* The _USE_LFN option switches the LFN support. / / 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect. @@ -105,12 +105,12 @@ / ff_memalloc() and ff_memfree() must be added to the project. */ -#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */ +#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */ /* To switch the character code set on FatFs API to Unicode, / enable LFN feature and set _LFN_UNICODE to 1. */ -#define _FS_RPATH 2 /* 0 to 2 */ +#define _FS_RPATH 2 /* 0 to 2 */ /* The _FS_RPATH option configures relative path feature. / / 0: Disable relative path feature and remove related functions. @@ -125,11 +125,11 @@ / Physical Drive Configurations /----------------------------------------------------------------------------*/ -#define _VOLUMES 1 +#define _VOLUMES 1 /* Number of volumes (logical drives) to be used. */ -#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */ +#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */ /* Maximum sector size to be handled. / Always set 512 for memory card and hard disk but a larger value may be / required for floppy disk (512/1024) and optical disk (512/2048). @@ -137,13 +137,13 @@ / to the disk_ioctl function. */ -#define _MULTI_PARTITION 0 /* 0:Single partition or 1:Multiple partition */ +#define _MULTI_PARTITION 0 /* 0:Single partition or 1:Multiple partition */ /* When set to 0, each volume is bound to the same physical drive number and / it can mount only first primaly partition. When it is set to 1, each volume / is tied to the partitions listed in VolToPart[]. */ -#define _USE_ERASE 0 /* 0:Disable or 1:Enable */ +#define _USE_ERASE 0 /* 0:Disable or 1:Enable */ /* To enable sector erase feature, set _USE_ERASE to 1. */ @@ -152,7 +152,7 @@ / System Configurations /----------------------------------------------------------------------------*/ -#define _WORD_ACCESS 0 /* 0 or 1 */ +#define _WORD_ACCESS 0 /* 0 or 1 */ /* Set 0 first and it is always compatible with all platforms. The _WORD_ACCESS / option defines which access method is used to the word data on the FAT volume. / @@ -168,9 +168,9 @@ /* Include a header file here to define sync object types on the O/S */ /* #include , , or ohters. */ -#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */ -#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */ -#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */ +#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */ +#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */ +#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */ /* The _FS_REENTRANT option switches the reentrancy of the FatFs module. / @@ -180,7 +180,7 @@ / function must be added to the project. */ -#define _FS_SHARE 0 /* 0:Disable or >=1:Enable */ +#define _FS_SHARE 0 /* 0:Disable or >=1:Enable */ /* To enable file shareing feature, set _FS_SHARE to 1 or greater. The value defines how many files can be opened simultaneously. */ diff --git a/src/fileops.c b/src/fileops.c index d5c5a60..8255a0e 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -37,81 +37,113 @@ WCHAR ff_convert(WCHAR w, UINT dir) { int newcard; -void file_init() { - file_res=f_mount(0, &fatfs); - newcard = 0; +void file_init() +{ + file_res = f_mount( 0, &fatfs ); + newcard = 0; } -void file_reinit(void) { - disk_init(); - file_init(); +void file_reinit( void ) +{ + disk_init(); + file_init(); } -FRESULT dir_open_by_filinfo(DIR* dir, FILINFO* fno) { - return l_opendirbycluster(&fatfs, dir, (TCHAR*)"", fno->clust); +FRESULT dir_open_by_filinfo( DIR *dir, FILINFO *fno ) +{ + return l_opendirbycluster( &fatfs, dir, ( TCHAR * )"", fno->clust ); } -void file_open_by_filinfo(FILINFO* fno) { - file_res = l_openfilebycluster(&fatfs, &file_handle, (TCHAR*)"", fno->clust, fno->fsize); +void file_open_by_filinfo( FILINFO *fno ) +{ + file_res = l_openfilebycluster( &fatfs, &file_handle, ( TCHAR * )"", fno->clust, fno->fsize ); } -void file_open(const uint8_t* filename, BYTE flags) { - if (disk_state == DISK_CHANGED) { - file_reinit(); - newcard = 1; - } - file_res = f_open(&file_handle, (TCHAR*)filename, flags); - file_block_off = sizeof(file_buf); - file_block_max = sizeof(file_buf); - file_status = file_res ? FILE_ERR : FILE_OK; +void file_open( const uint8_t *filename, BYTE flags ) +{ + if ( disk_state == DISK_CHANGED ) + { + file_reinit(); + newcard = 1; + } + + file_res = f_open( &file_handle, ( TCHAR * )filename, flags ); + file_block_off = sizeof( file_buf ); + file_block_max = sizeof( file_buf ); + file_status = file_res ? FILE_ERR : FILE_OK; } -void file_close() { - file_res = f_close(&file_handle); +void file_close() +{ + file_res = f_close( &file_handle ); } -void file_seek(uint32_t offset) { - file_res = f_lseek(&file_handle, (DWORD)offset); +void file_seek( uint32_t offset ) +{ + file_res = f_lseek( &file_handle, ( DWORD )offset ); } -UINT file_read() { - UINT bytes_read; - file_res = f_read(&file_handle, file_buf, sizeof(file_buf), &bytes_read); - return bytes_read; +UINT file_read() +{ + UINT bytes_read; + file_res = f_read( &file_handle, file_buf, sizeof( file_buf ), &bytes_read ); + return bytes_read; } -UINT file_write() { - UINT bytes_written; - file_res = f_write(&file_handle, file_buf, sizeof(file_buf), &bytes_written); - if(bytes_written < sizeof(file_buf)) { - printf("wrote less than expected - card full?\n"); - } - return bytes_written; +UINT file_write() +{ + UINT bytes_written; + file_res = f_write( &file_handle, file_buf, sizeof( file_buf ), &bytes_written ); + + if ( bytes_written < sizeof( file_buf ) ) + { + printf( "wrote less than expected - card full?\n" ); + } + + return bytes_written; } -UINT file_readblock(void* buf, uint32_t addr, uint16_t size) { - UINT bytes_read; - file_res = f_lseek(&file_handle, addr); - if(file_handle.fptr != addr) { - return 0; - } - file_res = f_read(&file_handle, buf, size, &bytes_read); - return bytes_read; +UINT file_readblock( void *buf, uint32_t addr, uint16_t size ) +{ + UINT bytes_read; + file_res = f_lseek( &file_handle, addr ); + + if ( file_handle.fptr != addr ) + { + return 0; + } + + file_res = f_read( &file_handle, buf, size, &bytes_read ); + return bytes_read; } -UINT file_writeblock(void* buf, uint32_t addr, uint16_t size) { - UINT bytes_written; - file_res = f_lseek(&file_handle, addr); - if(file_res) return 0; - file_res = f_write(&file_handle, buf, size, &bytes_written); - return bytes_written; +UINT file_writeblock( void *buf, uint32_t addr, uint16_t size ) +{ + UINT bytes_written; + file_res = f_lseek( &file_handle, addr ); + + if ( file_res ) + { + return 0; + } + + file_res = f_write( &file_handle, buf, size, &bytes_written ); + return bytes_written; } -uint8_t file_getc() { - if(file_block_off == file_block_max) { - file_block_max = file_read(); - if(file_block_max == 0) file_status = FILE_EOF; - file_block_off = 0; - } - return file_buf[file_block_off++]; +uint8_t file_getc() +{ + if ( file_block_off == file_block_max ) + { + file_block_max = file_read(); + + if ( file_block_max == 0 ) + { + file_status = FILE_EOF; + } + + file_block_off = 0; + } + + return file_buf[file_block_off++]; } diff --git a/src/fileops.h b/src/fileops.h index f3b3c3d..6faa50b 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -29,7 +29,7 @@ #include #include "ff.h" -enum filestates { FILE_OK=0, FILE_ERR, FILE_EOF }; +enum filestates { FILE_OK = 0, FILE_ERR, FILE_EOF }; BYTE file_buf[512]; FATFS fatfs; @@ -39,16 +39,16 @@ uint8_t file_lfn[258]; uint16_t file_block_off, file_block_max; enum filestates file_status; -void file_init(void); -void file_open(const uint8_t* filename, BYTE flags); -FRESULT dir_open_by_filinfo(DIR* dir, FILINFO* fno_param); -void file_open_by_filinfo(FILINFO* fno); -void file_close(void); -void file_seek(uint32_t offset); -UINT file_read(void); -UINT file_write(void); -UINT file_readblock(void* buf, uint32_t addr, uint16_t size); -UINT file_writeblock(void* buf, uint32_t addr, uint16_t size); +void file_init( void ); +void file_open( const uint8_t *filename, BYTE flags ); +FRESULT dir_open_by_filinfo( DIR *dir, FILINFO *fno_param ); +void file_open_by_filinfo( FILINFO *fno ); +void file_close( void ); +void file_seek( uint32_t offset ); +UINT file_read( void ); +UINT file_write( void ); +UINT file_readblock( void *buf, uint32_t addr, uint16_t size ); +UINT file_writeblock( void *buf, uint32_t addr, uint16_t size ); -uint8_t file_getc(void); +uint8_t file_getc( void ); #endif diff --git a/src/filetypes.c b/src/filetypes.c index 686063d..13a7e1b 100644 --- a/src/filetypes.c +++ b/src/filetypes.c @@ -36,301 +36,428 @@ #include "led.h" #include "sort.h" -uint16_t scan_flat(const char* path) { - DIR dir; - FRESULT res; - FILINFO fno; - fno.lfname = NULL; - res = f_opendir(&dir, (TCHAR*)path); - uint16_t numentries = 0; - if (res == FR_OK) { - for (;;) { - res = f_readdir(&dir, &fno); - if(res != FR_OK || fno.fname[0] == 0)break; - numentries++; +uint16_t scan_flat( const char *path ) +{ + DIR dir; + FRESULT res; + FILINFO fno; + fno.lfname = NULL; + res = f_opendir( &dir, ( TCHAR * )path ); + uint16_t numentries = 0; + + if ( res == FR_OK ) + { + for ( ;; ) + { + res = f_readdir( &dir, &fno ); + + if ( res != FR_OK || fno.fname[0] == 0 ) + { + break; + } + + numentries++; + } } - } - return numentries; + + return numentries; } -uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_tgt) { - DIR dir; - FILINFO fno; - FRESULT res; - uint8_t len; - TCHAR* fn; - static unsigned char depth = 0; - static uint32_t crc, fncrc; - static uint32_t db_tgt; - static uint32_t next_subdir_tgt; - static uint32_t parent_tgt; - static uint32_t dir_end = 0; -/* static uint8_t was_empty = 0;*/ - static uint16_t num_files_total = 0; - static uint16_t num_dirs_total = 0; - uint32_t dir_tgt; - uint32_t switched_dir_tgt = 0; - uint16_t numentries; - uint32_t dirsize; - uint8_t pass = 0; - char buf[7]; - char *size_units[3] = {" ", "k", "M"}; - uint32_t entry_fsize; - uint8_t entry_unit_idx; - uint16_t entrycnt; +uint32_t scan_dir( char *path, FILINFO *fno_param, char mkdb, uint32_t this_dir_tgt ) +{ + DIR dir; + FILINFO fno; + FRESULT res; + uint8_t len; + TCHAR *fn; + static unsigned char depth = 0; + static uint32_t crc, fncrc; + static uint32_t db_tgt; + static uint32_t next_subdir_tgt; + static uint32_t parent_tgt; + static uint32_t dir_end = 0; + static uint8_t was_empty = 0; + static uint16_t num_files_total = 0; + static uint16_t num_dirs_total = 0; + uint32_t dir_tgt; + uint32_t switched_dir_tgt = 0; + uint16_t numentries; + uint32_t dirsize; + uint8_t pass = 0; + char buf[7]; + char *size_units[3] = {" ", "k", "M"}; + uint32_t entry_fsize; + uint8_t entry_unit_idx; + uint16_t entrycnt; - dir_tgt = this_dir_tgt; - if(depth==0) { - crc = 0; - db_tgt = SRAM_DB_ADDR+0x10; - dir_tgt = SRAM_DIR_ADDR; - next_subdir_tgt = SRAM_DIR_ADDR; - this_dir_tgt = SRAM_DIR_ADDR; - parent_tgt = 0; - printf("root dir @%lx\n", dir_tgt); - } + dir_tgt = this_dir_tgt; - fno.lfsize = 255; - fno.lfname = (TCHAR*)file_lfn; - numentries=0; - for(pass = 0; pass < (mkdb ? 2 : 1); pass++) { - if(pass) { - dirsize = 4*(numentries); - if(((next_subdir_tgt + dirsize + 8) & 0xff0000) > (next_subdir_tgt & 0xff0000)) { - printf("switchdir! old=%lX ", next_subdir_tgt + dirsize + 4); - next_subdir_tgt &= 0xffff0000; - next_subdir_tgt += 0x00010004; - printf("new=%lx\n", next_subdir_tgt); - dir_tgt &= 0xffff0000; - dir_tgt += 0x00010004; - } - switched_dir_tgt = dir_tgt; - next_subdir_tgt += dirsize + 4; - if(parent_tgt) next_subdir_tgt += 4; - if(next_subdir_tgt > dir_end) { - dir_end = next_subdir_tgt; - } - DBG_FS printf("path=%s depth=%d ptr=%lx entries=%d parent=%lx next subdir @%lx\n", path, depth, db_tgt, numentries, parent_tgt, next_subdir_tgt); - if(mkdb) { - num_dirs_total++; -// printf("d=%d Saving %lx to Address %lx [end]\n", depth, 0L, next_subdir_tgt - 4); - sram_writelong(0L, next_subdir_tgt - 4); - } + if ( depth == 0 ) + { + crc = 0; + db_tgt = SRAM_DB_ADDR + 0x10; + dir_tgt = SRAM_DIR_ADDR; + next_subdir_tgt = SRAM_DIR_ADDR; + this_dir_tgt = SRAM_DIR_ADDR; + parent_tgt = 0; + printf( "root dir @%lx\n", dir_tgt ); } - if(fno_param) { - res = dir_open_by_filinfo(&dir, fno_param); - } else { - res = f_opendir(&dir, path); - } - if (res == FR_OK) { - if(pass && parent_tgt && mkdb) { - /* write backlink to parent dir - switch to next bank if record does not fit in current bank */ - if((db_tgt&0xffff) > ((0x10000-(sizeof(next_subdir_tgt)+sizeof(len)+4))&0xffff)) { - printf("switch! old=%lx ", db_tgt); - db_tgt &= 0xffff0000; - db_tgt += 0x00010000; - printf("new=%lx\n", db_tgt); - } -// printf("writing link to parent, %lx to address %lx [../]\n", parent_tgt-SRAM_MENU_ADDR, db_tgt); - sram_writelong((parent_tgt-SRAM_MENU_ADDR), db_tgt); - sram_writebyte(0, db_tgt+sizeof(next_subdir_tgt)); - sram_writeblock("../\0", db_tgt+sizeof(next_subdir_tgt)+sizeof(len), 4); - sram_writelong((db_tgt-SRAM_MENU_ADDR)|((uint32_t)0x81<<24), dir_tgt); - db_tgt += sizeof(next_subdir_tgt)+sizeof(len)+4; - dir_tgt += 4; - } - len = strlen((char*)path); - /* scan at most DIR_FILE_MAX entries per directory */ - for(entrycnt=0; entrycnt < DIR_FILE_MAX; entrycnt++) { -// toggle_read_led(); - res = f_readdir(&dir, &fno); - if (res != FR_OK || fno.fname[0] == 0) { - if(pass) { -/* if(!numentries) was_empty=1;*/ - } - break; - } - fn = *fno.lfname ? fno.lfname : fno.fname; - if ((*fn == '.') || !(strncasecmp(fn, SYS_DIR_NAME, sizeof(SYS_DIR_NAME)))) continue; - if (fno.fattrib & AM_DIR) { - depth++; - if(depth < FS_MAX_DEPTH) { - numentries++; - if(pass && mkdb) { - path[len]='/'; - strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len); - uint16_t pathlen = 0; - uint32_t old_db_tgt = 0; - if(mkdb) { - pathlen = strlen(path); - DBG_FS printf("d=%d Saving %lx to Address %lx [dir]\n", depth, db_tgt, dir_tgt); - /* save element: - - path name - - pointer to sub dir structure */ - if((db_tgt&0xffff) > ((0x10000-(sizeof(next_subdir_tgt) + sizeof(len) + pathlen + 2))&0xffff)) { - printf("switch! old=%lx ", db_tgt); - db_tgt &= 0xffff0000; - db_tgt += 0x00010000; - printf("new=%lx\n", db_tgt); - } - /* write element pointer to current dir structure */ - sram_writelong((db_tgt-SRAM_MENU_ADDR)|((uint32_t)0x80<<24), dir_tgt); - /* save element: - - path name - - pointer to sub dir structure - moved below */ - old_db_tgt = db_tgt; - db_tgt += sizeof(next_subdir_tgt) + sizeof(len) + pathlen + 2; - } - parent_tgt = this_dir_tgt; - /* scan subdir before writing current dir element to account for bank switches */ - uint32_t corrected_subdir_tgt = scan_dir(path, &fno, mkdb, next_subdir_tgt); - if(mkdb) { - DBG_FS printf(" Saving dir descriptor to %lx tgt=%lx, path=%s\n", old_db_tgt, corrected_subdir_tgt, path); - sram_writelong((corrected_subdir_tgt-SRAM_MENU_ADDR), old_db_tgt); - sram_writebyte(len+1, old_db_tgt+sizeof(next_subdir_tgt)); - sram_writeblock(path, old_db_tgt+sizeof(next_subdir_tgt)+sizeof(len), pathlen); - sram_writeblock("/\0", old_db_tgt + sizeof(next_subdir_tgt) + sizeof(len) + pathlen, 2); - } - dir_tgt += 4; -/* was_empty = 0;*/ - } else if(!mkdb) { - path[len]='/'; - strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len); - scan_dir(path, &fno, mkdb, next_subdir_tgt); + + fno.lfsize = 255; + fno.lfname = ( TCHAR * )file_lfn; + numentries = 0; + + for ( pass = 0; pass < ( mkdb ? 2 : 1 ); pass++ ) + { + if ( pass ) + { + dirsize = 4 * ( numentries ); + + if ( ( ( next_subdir_tgt + dirsize + 8 ) & 0xff0000 ) > ( next_subdir_tgt & 0xff0000 ) ) + { + printf( "switchdir! old=%lX ", next_subdir_tgt + dirsize + 4 ); + next_subdir_tgt &= 0xffff0000; + next_subdir_tgt += 0x00010004; + printf( "new=%lx\n", next_subdir_tgt ); + dir_tgt &= 0xffff0000; + dir_tgt += 0x00010004; } - } - depth--; - path[len]=0; - } else { - SNES_FTYPE type = determine_filetype((char*)fn); - if(type != TYPE_UNKNOWN) { - numentries++; - if(pass) { - if(mkdb) { - num_files_total++; -/* snes_romprops_t romprops; */ - path[len]='/'; - strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len); - uint16_t pathlen = strlen(path); - switch(type) { - case TYPE_IPS: - case TYPE_SMC: - case TYPE_SPC: - /* write element pointer to current dir structure */ - DBG_FS printf("d=%d Saving %lX to Address %lX [file %s]\n", depth, db_tgt, dir_tgt, path); - if((db_tgt&0xffff) > ((0x10000-(sizeof(len) + pathlen + sizeof(buf)-1 + 1))&0xffff)) { - printf("switch! old=%lx ", db_tgt); - db_tgt &= 0xffff0000; - db_tgt += 0x00010000; - printf("new=%lx\n", db_tgt); + + switched_dir_tgt = dir_tgt; + next_subdir_tgt += dirsize + 4; + + if ( parent_tgt ) + { + next_subdir_tgt += 4; + } + + if ( next_subdir_tgt > dir_end ) + { + dir_end = next_subdir_tgt; + } + + DBG_FS printf( "path=%s depth=%d ptr=%lx entries=%d parent=%lx next subdir @%lx\n", path, depth, db_tgt, numentries, + parent_tgt, next_subdir_tgt ); + + if ( mkdb ) + { + num_dirs_total++; + // printf("d=%d Saving %lx to Address %lx [end]\n", depth, 0L, next_subdir_tgt - 4); + sram_writelong( 0L, next_subdir_tgt - 4 ); + } + } + + if ( fno_param ) + { + res = dir_open_by_filinfo( &dir, fno_param ); + } + else + { + res = f_opendir( &dir, path ); + } + + if ( res == FR_OK ) + { + if ( pass && parent_tgt && mkdb ) + { + /* write backlink to parent dir + switch to next bank if record does not fit in current bank */ + if ( ( db_tgt & 0xffff ) > ( ( 0x10000 - ( sizeof( next_subdir_tgt ) + sizeof( len ) + 4 ) ) & 0xffff ) ) + { + printf( "switch! old=%lx ", db_tgt ); + db_tgt &= 0xffff0000; + db_tgt += 0x00010000; + printf( "new=%lx\n", db_tgt ); + } + + // printf("writing link to parent, %lx to address %lx [../]\n", parent_tgt-SRAM_MENU_ADDR, db_tgt); + sram_writelong( ( parent_tgt - SRAM_MENU_ADDR ), db_tgt ); + sram_writebyte( 0, db_tgt + sizeof( next_subdir_tgt ) ); + sram_writeblock( "../\0", db_tgt + sizeof( next_subdir_tgt ) + sizeof( len ), 4 ); + sram_writelong( ( db_tgt - SRAM_MENU_ADDR ) | ( ( uint32_t )0x81 << 24 ), dir_tgt ); + db_tgt += sizeof( next_subdir_tgt ) + sizeof( len ) + 4; + dir_tgt += 4; + } + + len = strlen( ( char * )path ); + + /* scan at most DIR_FILE_MAX entries per directory */ + for ( entrycnt = 0; entrycnt < DIR_FILE_MAX; entrycnt++ ) + { + // toggle_read_led(); + res = f_readdir( &dir, &fno ); + + if ( res != FR_OK || fno.fname[0] == 0 ) + { + if ( pass ) + { + /* if(!numentries) was_empty=1;*/ } - sram_writelong((db_tgt-SRAM_MENU_ADDR) | ((uint32_t)type << 24), dir_tgt); - dir_tgt += 4; - /* save element: - - index of last slash character - - file name - - file size */ -/* sram_writeblock((uint8_t*)&romprops, db_tgt, sizeof(romprops)); */ - entry_fsize = fno.fsize; - entry_unit_idx = 0; - while(entry_fsize > 9999) { - entry_fsize >>= 10; - entry_unit_idx++; - } - snprintf(buf, sizeof(buf), "% 5ld", entry_fsize); - strncat(buf, size_units[entry_unit_idx], 1); - sram_writeblock(buf, db_tgt, sizeof(buf)-1); - sram_writebyte(len+1, db_tgt + sizeof(buf)-1); - sram_writeblock(path, db_tgt + sizeof(len) + sizeof(buf)-1, pathlen + 1); -// sram_writelong(fno.fsize, db_tgt + sizeof(len) + pathlen + 1); - db_tgt += sizeof(len) + pathlen + sizeof(buf)-1 + 1; + break; - case TYPE_UNKNOWN: - default: - break; } - path[len] = 0; -/* printf("%s ", path); - _delay_ms(30); */ - } - } else { - TCHAR* fn2 = fn; - fncrc = 0; - while(*fn2 != 0) { - fncrc += crc_xmodem_update(fncrc, *((unsigned char*)fn2++)); - } - crc += fncrc; + + fn = *fno.lfname ? fno.lfname : fno.fname; + + if ( ( *fn == '.' ) || !( strncasecmp( fn, SYS_DIR_NAME, sizeof( SYS_DIR_NAME ) ) ) ) + { + continue; + } + + if ( fno.fattrib & AM_DIR ) + { + depth++; + + if ( depth < FS_MAX_DEPTH ) + { + numentries++; + + if ( pass && mkdb ) + { + path[len] = '/'; + strncpy( path + len + 1, ( char * )fn, sizeof( fs_path ) - len ); + uint16_t pathlen = 0; + uint32_t old_db_tgt = 0; + + if ( mkdb ) + { + pathlen = strlen( path ); + DBG_FS printf( "d=%d Saving %lx to Address %lx [dir]\n", depth, db_tgt, dir_tgt ); + + /* save element: + - path name + - pointer to sub dir structure */ + if ( ( db_tgt & 0xffff ) > ( ( 0x10000 - ( sizeof( next_subdir_tgt ) + sizeof( len ) + pathlen + 2 ) ) & 0xffff ) ) + { + printf( "switch! old=%lx ", db_tgt ); + db_tgt &= 0xffff0000; + db_tgt += 0x00010000; + printf( "new=%lx\n", db_tgt ); + } + + /* write element pointer to current dir structure */ + sram_writelong( ( db_tgt - SRAM_MENU_ADDR ) | ( ( uint32_t )0x80 << 24 ), dir_tgt ); + /* save element: + - path name + - pointer to sub dir structure + moved below */ + old_db_tgt = db_tgt; + db_tgt += sizeof( next_subdir_tgt ) + sizeof( len ) + pathlen + 2; + } + + parent_tgt = this_dir_tgt; + /* scan subdir before writing current dir element to account for bank switches */ + uint32_t corrected_subdir_tgt = scan_dir( path, &fno, mkdb, next_subdir_tgt ); + + if ( mkdb ) + { + DBG_FS printf( " Saving dir descriptor to %lx tgt=%lx, path=%s\n", old_db_tgt, corrected_subdir_tgt, path ); + sram_writelong( ( corrected_subdir_tgt - SRAM_MENU_ADDR ), old_db_tgt ); + sram_writebyte( len + 1, old_db_tgt + sizeof( next_subdir_tgt ) ); + sram_writeblock( path, old_db_tgt + sizeof( next_subdir_tgt ) + sizeof( len ), pathlen ); + sram_writeblock( "/\0", old_db_tgt + sizeof( next_subdir_tgt ) + sizeof( len ) + pathlen, 2 ); + } + + dir_tgt += 4; + /* was_empty = 0;*/ + } + else if ( !mkdb ) + { + path[len] = '/'; + strncpy( path + len + 1, ( char * )fn, sizeof( fs_path ) - len ); + scan_dir( path, &fno, mkdb, next_subdir_tgt ); + } + } + + depth--; + path[len] = 0; + } + else + { + SNES_FTYPE type = determine_filetype( ( char * )fn ); + + if ( type != TYPE_UNKNOWN ) + { + numentries++; + + if ( pass ) + { + if ( mkdb ) + { + num_files_total++; + /* snes_romprops_t romprops; */ + path[len] = '/'; + strncpy( path + len + 1, ( char * )fn, sizeof( fs_path ) - len ); + uint16_t pathlen = strlen( path ); + + switch ( type ) + { + case TYPE_IPS: + case TYPE_SMC: + case TYPE_SPC: + /* write element pointer to current dir structure */ + DBG_FS printf( "d=%d Saving %lX to Address %lX [file %s]\n", depth, db_tgt, dir_tgt, path ); + + if ( ( db_tgt & 0xffff ) > ( ( 0x10000 - ( sizeof( len ) + pathlen + sizeof( buf ) - 1 + 1 ) ) & 0xffff ) ) + { + printf( "switch! old=%lx ", db_tgt ); + db_tgt &= 0xffff0000; + db_tgt += 0x00010000; + printf( "new=%lx\n", db_tgt ); + } + + sram_writelong( ( db_tgt - SRAM_MENU_ADDR ) | ( ( uint32_t )type << 24 ), dir_tgt ); + dir_tgt += 4; + /* save element: + - index of last slash character + - file name + - file size */ + /* sram_writeblock((uint8_t*)&romprops, db_tgt, sizeof(romprops)); */ + entry_fsize = fno.fsize; + entry_unit_idx = 0; + + while ( entry_fsize > 9999 ) + { + entry_fsize >>= 10; + entry_unit_idx++; + } + + snprintf( buf, sizeof( buf ), "% 5ld", entry_fsize ); + strncat( buf, size_units[entry_unit_idx], 1 ); + sram_writeblock( buf, db_tgt, sizeof( buf ) - 1 ); + sram_writebyte( len + 1, db_tgt + sizeof( buf ) - 1 ); + sram_writeblock( path, db_tgt + sizeof( len ) + sizeof( buf ) - 1, pathlen + 1 ); + // sram_writelong(fno.fsize, db_tgt + sizeof(len) + pathlen + 1); + db_tgt += sizeof( len ) + pathlen + sizeof( buf ) - 1 + 1; + break; + + case TYPE_UNKNOWN: + default: + break; + } + + path[len] = 0; + /* printf("%s ", path); + _delay_ms(30); */ + } + } + else + { + TCHAR *fn2 = fn; + fncrc = 0; + + while ( *fn2 != 0 ) + { + fncrc += crc_xmodem_update( fncrc, *( ( unsigned char * )fn2++ ) ); + } + + crc += fncrc; + } + } + } } - } } - } - } else uart_putc(0x30+res); - } - DBG_FS printf("db_tgt=%lx dir_end=%lx\n", db_tgt, dir_end); - sram_writelong(db_tgt, SRAM_DB_ADDR+4); - sram_writelong(dir_end, SRAM_DB_ADDR+8); - sram_writeshort(num_files_total, SRAM_DB_ADDR+12); - sram_writeshort(num_dirs_total, SRAM_DB_ADDR+14); - if(depth==0) return crc; - else return switched_dir_tgt; - return was_empty; // tricky! -} - - -SNES_FTYPE determine_filetype(char* filename) { - char* ext = strrchr(filename, '.'); - if(ext == NULL) - return TYPE_UNKNOWN; - if( (!strcasecmp(ext+1, "SMC")) - ||(!strcasecmp(ext+1, "SFC")) - ||(!strcasecmp(ext+1, "FIG")) - ||(!strcasecmp(ext+1, "BS")) - ) { - return TYPE_SMC; - } -/* if( (!strcasecmp(ext+1, "IPS")) - ||(!strcasecmp(ext+1, "UPS")) - ) { - return TYPE_IPS; - }*/ - if(!strcasecmp(ext+1, "SPC")) { - return TYPE_SPC; - } - return TYPE_UNKNOWN; -} - -FRESULT get_db_id(uint32_t* id) { - file_open((uint8_t*)"/sd2snes/sd2snes.db", FA_READ); - if(file_res == FR_OK) { - file_readblock(id, 0, 4); -/* XXX */// *id=0xdead; - file_close(); - } else { - *id=0xdeadbeef; - } - return file_res; -} - -int get_num_dirent(uint32_t addr) { - int result = 0; - while(sram_readlong(addr+result*4)) { - result++; - } - return result; -} - -void sort_all_dir(uint32_t endaddr) { - uint32_t entries = 0; - uint32_t current_base = SRAM_DIR_ADDR; - while(current_base<(endaddr)) { - while(sram_readlong(current_base+entries*4)) { - entries++; + else + { + uart_putc( 0x30 + res ); + } + } + + DBG_FS printf( "db_tgt=%lx dir_end=%lx\n", db_tgt, dir_end ); + sram_writelong( db_tgt, SRAM_DB_ADDR + 4 ); + sram_writelong( dir_end, SRAM_DB_ADDR + 8 ); + sram_writeshort( num_files_total, SRAM_DB_ADDR + 12 ); + sram_writeshort( num_dirs_total, SRAM_DB_ADDR + 14 ); + + if ( depth == 0 ) + { + return crc; + } + else + { + return switched_dir_tgt; + } + + return was_empty; // tricky! +} + + +SNES_FTYPE determine_filetype( char *filename ) +{ + char *ext = strrchr( filename, '.' ); + + if ( ext == NULL ) + { + return TYPE_UNKNOWN; + } + + if ( ( !strcasecmp( ext + 1, "SMC" ) ) + || ( !strcasecmp( ext + 1, "SFC" ) ) + || ( !strcasecmp( ext + 1, "FIG" ) ) + || ( !strcasecmp( ext + 1, "BS" ) ) + ) + { + return TYPE_SMC; + } + + /* if( (!strcasecmp(ext+1, "IPS")) + ||(!strcasecmp(ext+1, "UPS")) + ) { + return TYPE_IPS; + }*/ + if ( !strcasecmp( ext + 1, "SPC" ) ) + { + return TYPE_SPC; + } + + return TYPE_UNKNOWN; +} + +FRESULT get_db_id( uint32_t *id ) +{ + file_open( ( uint8_t * )"/sd2snes/sd2snes.db", FA_READ ); + + if ( file_res == FR_OK ) + { + file_readblock( id, 0, 4 ); + /* XXX */// *id=0xdead; + file_close(); + } + else + { + *id = 0xdeadbeef; + } + + return file_res; +} + +int get_num_dirent( uint32_t addr ) +{ + int result = 0; + + while ( sram_readlong( addr + result * 4 ) ) + { + result++; + } + + return result; +} + +void sort_all_dir( uint32_t endaddr ) +{ + uint32_t entries = 0; + uint32_t current_base = SRAM_DIR_ADDR; + + while ( current_base < ( endaddr ) ) + { + while ( sram_readlong( current_base + entries * 4 ) ) + { + entries++; + } + + printf( "sorting dir @%lx, entries: %ld\n", current_base, entries ); + sort_dir( current_base, entries ); + current_base += 4 * entries + 4; + entries = 0; } - printf("sorting dir @%lx, entries: %ld\n", current_base, entries); - sort_dir(current_base, entries); - current_base += 4*entries + 4; - entries = 0; - } } diff --git a/src/filetypes.h b/src/filetypes.h index 2e91e9f..0776ae0 100644 --- a/src/filetypes.h +++ b/src/filetypes.h @@ -35,24 +35,25 @@ #include "ff.h" -#define FS_MAX_DEPTH (10) -#define SYS_DIR_NAME ((const char*)"sd2snes") -typedef enum { - TYPE_UNKNOWN = 0, /* 0 */ - TYPE_SMC, /* 1 */ - TYPE_SRM, /* 2 */ - TYPE_SPC, /* 3 */ - TYPE_IPS /* 4 */ +#define FS_MAX_DEPTH (10) +#define SYS_DIR_NAME ((const char*)"sd2snes") +typedef enum +{ + TYPE_UNKNOWN = 0, /* 0 */ + TYPE_SMC, /* 1 */ + TYPE_SRM, /* 2 */ + TYPE_SPC, /* 3 */ + TYPE_IPS /* 4 */ } SNES_FTYPE; char fs_path[256]; -SNES_FTYPE determine_filetype(char* filename); +SNES_FTYPE determine_filetype( char *filename ); //uint32_t scan_fs(); -uint16_t scan_flat(const char* path); -uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_subdir_tgt); -FRESULT get_db_id(uint32_t*); -int get_num_dirent(uint32_t addr); -void sort_all_dir(uint32_t endaddr); +uint16_t scan_flat( const char *path ); +uint32_t scan_dir( char *path, FILINFO *fno_param, char mkdb, uint32_t this_subdir_tgt ); +FRESULT get_db_id( uint32_t * ); +int get_num_dirent( uint32_t addr ); +void sort_all_dir( uint32_t endaddr ); #endif diff --git a/src/fpga.c b/src/fpga.c index da0157f..a448a81 100644 --- a/src/fpga.c +++ b/src/fpga.c @@ -52,147 +52,208 @@ #include "rle.h" #include "cfgware.h" -void fpga_set_prog_b(uint8_t val) { - if(val) - BITBAND(PROGBREG->FIOSET, PROGBBIT) = 1; - else - BITBAND(PROGBREG->FIOCLR, PROGBBIT) = 1; +void fpga_set_prog_b( uint8_t val ) +{ + if ( val ) + { + BITBAND( PROGBREG->FIOSET, PROGBBIT ) = 1; + } + else + { + BITBAND( PROGBREG->FIOCLR, PROGBBIT ) = 1; + } } -void fpga_set_cclk(uint8_t val) { - if(val) - BITBAND(CCLKREG->FIOSET, CCLKBIT) = 1; - else - BITBAND(CCLKREG->FIOCLR, CCLKBIT) = 1; +void fpga_set_cclk( uint8_t val ) +{ + if ( val ) + { + BITBAND( CCLKREG->FIOSET, CCLKBIT ) = 1; + } + else + { + BITBAND( CCLKREG->FIOCLR, CCLKBIT ) = 1; + } } -int fpga_get_initb() { - return BITBAND(INITBREG->FIOPIN, INITBBIT); +int fpga_get_initb() +{ + return BITBAND( INITBREG->FIOPIN, INITBBIT ); } -void fpga_init() { -/* mainly GPIO directions */ - BITBAND(CCLKREG->FIODIR, CCLKBIT) = 1; /* CCLK */ - BITBAND(DONEREG->FIODIR, DONEBIT) = 0; /* DONE */ - BITBAND(PROGBREG->FIODIR, PROGBBIT) = 1; /* PROG_B */ - BITBAND(DINREG->FIODIR, DINBIT) = 1; /* DIN */ - BITBAND(INITBREG->FIODIR, INITBBIT) = 0; /* INIT_B */ +void fpga_init() +{ + /* mainly GPIO directions */ + BITBAND( CCLKREG->FIODIR, CCLKBIT ) = 1; /* CCLK */ + BITBAND( DONEREG->FIODIR, DONEBIT ) = 0; /* DONE */ + BITBAND( PROGBREG->FIODIR, PROGBBIT ) = 1; /* PROG_B */ + BITBAND( DINREG->FIODIR, DINBIT ) = 1; /* DIN */ + BITBAND( INITBREG->FIODIR, INITBBIT ) = 0; /* INIT_B */ - LPC_GPIO2->FIOMASK1 = 0; + LPC_GPIO2->FIOMASK1 = 0; + SPI_OFFLOAD = 0; - SPI_OFFLOAD=0; - fpga_set_cclk(0); /* initial clk=0 */ + fpga_set_cclk( 0 ); /* initial clk=0 */ } -int fpga_get_done(void) { - return BITBAND(DONEREG->FIOPIN, DONEBIT); +int fpga_get_done( void ) +{ + return BITBAND( DONEREG->FIOPIN, DONEBIT ); } -void fpga_postinit() { - LPC_GPIO2->FIOMASK1 = 0; +void fpga_postinit() +{ + LPC_GPIO2->FIOMASK1 = 0; } -void fpga_pgm(uint8_t* filename) { - int MAXRETRIES = 10; - int retries = MAXRETRIES; - uint8_t data; - int i; - tick_t timeout; - do { - i=0; - timeout = getticks() + 100; - fpga_set_prog_b(0); -if(BITBAND(PROGBREG->FIOPIN, PROGBBIT)) { - printf("PROGB is stuck high!\n"); - led_panic(); -} - uart_putc('P'); - fpga_set_prog_b(1); - while(!fpga_get_initb()){ - if(getticks() > timeout) { - printf("no response from FPGA trying to initiate configuration!\n"); +void fpga_pgm( uint8_t *filename ) +{ + int MAXRETRIES = 10; + int retries = MAXRETRIES; + uint8_t data; + int i; + tick_t timeout; + + do + { + i = 0; + timeout = getticks() + 100; + fpga_set_prog_b( 0 ); + + if ( BITBAND( PROGBREG->FIOPIN, PROGBBIT ) ) + { + printf( "PROGB is stuck high!\n" ); + led_panic(); + } + + uart_putc( 'P' ); + fpga_set_prog_b( 1 ); + + while ( !fpga_get_initb() ) + { + if ( getticks() > timeout ) + { + printf( "no response from FPGA trying to initiate configuration!\n" ); + led_panic(); + } + }; + + if ( fpga_get_done() ) + { + printf( "DONE is stuck high!\n" ); + led_panic(); + } + + LPC_GPIO2->FIOMASK1 = ~( BV( 0 ) ); + uart_putc( 'p' ); + + + /* open configware file */ + file_open( filename, FA_READ ); + + if ( file_res ) + { + uart_putc( '?' ); + uart_putc( 0x30 + file_res ); + return; + } + + uart_putc( 'C' ); + + for ( ;; ) + { + data = rle_file_getc(); + i++; + + if ( file_status || file_res ) + { + break; /* error or eof */ + } + + FPGA_SEND_BYTE_SERIAL( data ); + } + + uart_putc( 'c' ); + file_close(); + printf( "fpga_pgm: %d bytes programmed\n", i ); + delay_ms( 1 ); + } + while ( !fpga_get_done() && retries-- ); + + if ( !fpga_get_done() ) + { + printf( "FPGA failed to configure after %d tries.\n", MAXRETRIES ); led_panic(); - } - }; - if(fpga_get_done()) { - printf("DONE is stuck high!\n"); - led_panic(); } - LPC_GPIO2->FIOMASK1 = ~(BV(0)); - uart_putc('p'); - - /* open configware file */ - file_open(filename, FA_READ); - if(file_res) { - uart_putc('?'); - uart_putc(0x30+file_res); - return; - } - uart_putc('C'); - - for (;;) { - data = rle_file_getc(); - i++; - if (file_status || file_res) break; /* error or eof */ - FPGA_SEND_BYTE_SERIAL(data); - } - uart_putc('c'); - file_close(); - printf("fpga_pgm: %d bytes programmed\n", i); - delay_ms(1); - } while (!fpga_get_done() && retries--); - if(!fpga_get_done()) { - printf("FPGA failed to configure after %d tries.\n", MAXRETRIES); - led_panic(); - } - printf("FPGA configured\n"); - fpga_postinit(); + printf( "FPGA configured\n" ); + fpga_postinit(); } -void fpga_rompgm() { - int MAXRETRIES = 10; - int retries = MAXRETRIES; - uint8_t data; - int i; - tick_t timeout; - do { - i=0; - timeout = getticks() + 100; - fpga_set_prog_b(0); - uart_putc('P'); - fpga_set_prog_b(1); - while(!fpga_get_initb()){ - if(getticks() > timeout) { - printf("no response from FPGA trying to initiate configuration!\n"); +void fpga_rompgm() +{ + int MAXRETRIES = 10; + int retries = MAXRETRIES; + uint8_t data; + int i; + tick_t timeout; + + do + { + i = 0; + timeout = getticks() + 100; + fpga_set_prog_b( 0 ); + uart_putc( 'P' ); + fpga_set_prog_b( 1 ); + + while ( !fpga_get_initb() ) + { + if ( getticks() > timeout ) + { + printf( "no response from FPGA trying to initiate configuration!\n" ); + led_panic(); + } + }; + + if ( fpga_get_done() ) + { + printf( "DONE is stuck high!\n" ); + led_panic(); + } + + LPC_GPIO2->FIOMASK1 = ~( BV( 0 ) ); + uart_putc( 'p' ); + + /* open configware file */ + rle_mem_init( cfgware, sizeof( cfgware ) ); + printf( "sizeof(cfgware) = %d\n", sizeof( cfgware ) ); + + for ( ;; ) + { + data = rle_mem_getc(); + + if ( rle_state ) + { + break; + } + + i++; + FPGA_SEND_BYTE_SERIAL( data ); + } + + uart_putc( 'c' ); + printf( "fpga_pgm: %d bytes programmed\n", i ); + delay_ms( 1 ); + } + while ( !fpga_get_done() && retries-- ); + + if ( !fpga_get_done() ) + { + printf( "FPGA failed to configure after %d tries.\n", MAXRETRIES ); led_panic(); - } - }; - if(fpga_get_done()) { - printf("DONE is stuck high!\n"); - led_panic(); } - LPC_GPIO2->FIOMASK1 = ~(BV(0)); - uart_putc('p'); - /* open configware file */ - rle_mem_init(cfgware, sizeof(cfgware)); - printf("sizeof(cfgware) = %d\n", sizeof(cfgware)); - for (;;) { - data = rle_mem_getc(); - if(rle_state) break; - i++; - FPGA_SEND_BYTE_SERIAL(data); - } - uart_putc('c'); - printf("fpga_pgm: %d bytes programmed\n", i); - delay_ms(1); - } while (!fpga_get_done() && retries--); - if(!fpga_get_done()) { - printf("FPGA failed to configure after %d tries.\n", MAXRETRIES); - led_panic(); - } - printf("FPGA configured\n"); - fpga_postinit(); + printf( "FPGA configured\n" ); + fpga_postinit(); } diff --git a/src/fpga.h b/src/fpga.h index 7ef783f..4b42d1a 100644 --- a/src/fpga.h +++ b/src/fpga.h @@ -30,14 +30,14 @@ #include #include "bits.h" -void fpga_set_prog_b(uint8_t val); -void fpga_set_cclk(uint8_t val); -int fpga_get_initb(void); +void fpga_set_prog_b( uint8_t val ); +void fpga_set_cclk( uint8_t val ); +int fpga_get_initb( void ); -void fpga_init(void); -void fpga_postinit(void); -void fpga_pgm(uint8_t* filename); -void fpga_rompgm(void); +void fpga_init( void ); +void fpga_postinit( void ); +void fpga_pgm( uint8_t *filename ); +void fpga_rompgm( void ); uint8_t SPI_OFFLOAD; @@ -54,16 +54,16 @@ uint8_t SPI_OFFLOAD; #define DONEBIT (22) -#define FPGA_TEST_TOKEN (0xa5) +#define FPGA_TEST_TOKEN (0xa5) // some macros for bulk transfers (faster) -#define FPGA_SEND_BYTE_SERIAL(data) do {SET_FPGA_DIN(data>>7); CCLK();\ -SET_FPGA_DIN(data>>6); CCLK(); SET_FPGA_DIN(data>>5); CCLK();\ -SET_FPGA_DIN(data>>4); CCLK(); SET_FPGA_DIN(data>>3); CCLK();\ -SET_FPGA_DIN(data>>2); CCLK(); SET_FPGA_DIN(data>>1); CCLK();\ -SET_FPGA_DIN(data); CCLK();} while (0) -#define SET_CCLK() do {BITBAND(LPC_GPIO0->FIOSET, 11) = 1;} while (0) -#define CLR_CCLK() do {BITBAND(LPC_GPIO0->FIOCLR, 11) = 1;} while (0) -#define CCLK() do {SET_CCLK(); CLR_CCLK();} while (0) -#define SET_FPGA_DIN(data) do {LPC_GPIO2->FIOPIN1 = data;} while (0) +#define FPGA_SEND_BYTE_SERIAL(data) do {SET_FPGA_DIN(data>>7); CCLK();\ + SET_FPGA_DIN(data>>6); CCLK(); SET_FPGA_DIN(data>>5); CCLK();\ + SET_FPGA_DIN(data>>4); CCLK(); SET_FPGA_DIN(data>>3); CCLK();\ + SET_FPGA_DIN(data>>2); CCLK(); SET_FPGA_DIN(data>>1); CCLK();\ + SET_FPGA_DIN(data); CCLK();} while (0) +#define SET_CCLK() do {BITBAND(LPC_GPIO0->FIOSET, 11) = 1;} while (0) +#define CLR_CCLK() do {BITBAND(LPC_GPIO0->FIOCLR, 11) = 1;} while (0) +#define CCLK() do {SET_CCLK(); CLR_CCLK();} while (0) +#define SET_FPGA_DIN(data) do {LPC_GPIO2->FIOPIN1 = data;} while (0) #endif diff --git a/src/fpga_spi.c b/src/fpga_spi.c index f432228..633587d 100644 --- a/src/fpga_spi.c +++ b/src/fpga_spi.c @@ -25,110 +25,110 @@ */ /* - SPI commands + SPI commands - cmd param function + cmd param function ============================================= - 0t bbhhll set address to 0xbbhhll - t = target - target: 0 = RAM - 1 = MSU Audio buffer - 2 = MSU Data buffer - targets 1 & 2 only require 2 address bytes to - be written. + 0t bbhhll set address to 0xbbhhll + t = target + target: 0 = RAM + 1 = MSU Audio buffer + 2 = MSU Data buffer + targets 1 & 2 only require 2 address bytes to + be written. - 10 bbhhll set SNES input address mask to 0xbbhhll - 20 bbhhll set SRAM address mask to 0xbbhhll + 10 bbhhll set SNES input address mask to 0xbbhhll + 20 bbhhll set SRAM address mask to 0xbbhhll - 3m - set mapper to m - 0=HiROM, 1=LoROM, 2=ExHiROM, 6=SF96, 7=Menu + 3m - set mapper to m + 0=HiROM, 1=LoROM, 2=ExHiROM, 6=SF96, 7=Menu - 4s - trigger SD DMA (512b from SD to memory) + 4s - trigger SD DMA (512b from SD to memory) s: Bit 2 = partial, Bit 1:0 = target target: see above - 60 xsssyeee set SD DMA partial transfer parameters - x: 0 = read from sector start (skip until - start offset reached) - 8 = assume mid-sector position and read - immediately - sss = start offset (msb first) - y: 0 = skip rest of SD sector - 8 = stop mid-sector if end offset reached - eee = end offset (msb first) + 60 xsssyeee set SD DMA partial transfer parameters + x: 0 = read from sector start (skip until + start offset reached) + 8 = assume mid-sector position and read + immediately + sss = start offset (msb first) + y: 0 = skip rest of SD sector + 8 = stop mid-sector if end offset reached + eee = end offset (msb first) - 8p - read (RAM only) - p: 0 = no increment after read - 8 = increment after read + 8p - read (RAM only) + p: 0 = no increment after read + 8 = increment after read - 9p {xx}* write xx - p: i-tt - tt = target (see above) - i = increment (see above) + 9p {xx}* write xx + p: i-tt + tt = target (see above) + i = increment (see above) - E0 ssrr set MSU-1 status register (=FPGA status [7:0]) - ss = bits to set in status register (1=set) - rr = bits to reset in status register (1=reset) + E0 ssrr set MSU-1 status register (=FPGA status [7:0]) + ss = bits to set in status register (1=set) + rr = bits to reset in status register (1=reset) - E1 - pause DAC - E2 - resume/play DAC - E3 - reset DAC playback pointer (0) - E4 hhll set MSU read pointer + E1 - pause DAC + E2 - resume/play DAC + E3 - reset DAC playback pointer (0) + E4 hhll set MSU read pointer - E5 tt{7} set RTC (SPC7110 format + 1000s of year, - nibbles packed) + E5 tt{7} set RTC (SPC7110 format + 1000s of year, + nibbles packed) eg 0x20111210094816 is 2011-12-10, 9:48:16 - E6 ssrr set/reset BS-X status register [7:0] - E7 - reset SRTC state - E8 - reset DSP program and data ROM write pointers - E9 hhmmllxxxx write+incr. DSP program ROM (xxxx=dummy writes) - EA hhllxxxx write+incr. DSP data ROM (xxxx=dummy writes) - EB - put DSP into reset - EC - release DSP from reset - ED - set feature enable bits (see below) - EE - set $213f override value (0=NTSC, 1=PAL) - F0 - receive test token (to see if FPGA is alive) - F1 - receive status (16bit, MSB first), see below + E6 ssrr set/reset BS-X status register [7:0] + E7 - reset SRTC state + E8 - reset DSP program and data ROM write pointers + E9 hhmmllxxxx write+incr. DSP program ROM (xxxx=dummy writes) + EA hhllxxxx write+incr. DSP data ROM (xxxx=dummy writes) + EB - put DSP into reset + EC - release DSP from reset + ED - set feature enable bits (see below) + EE - set $213f override value (0=NTSC, 1=PAL) + F0 - receive test token (to see if FPGA is alive) + F1 - receive status (16bit, MSB first), see below - F2 - get MSU data address (32bit, MSB first) - F3 - get MSU audio track no. (16bit, MSB first) - F4 - get MSU volume (8bit) + F2 - get MSU data address (32bit, MSB first) + F3 - get MSU audio track no. (16bit, MSB first) + F4 - get MSU volume (8bit) - FE - get SNES master clock frequency (32bit, MSB first) - measured 1x/sec - FF {xx}* echo (returns the sent data in the next byte) + FE - get SNES master clock frequency (32bit, MSB first) + measured 1x/sec + FF {xx}* echo (returns the sent data in the next byte) - FPGA status word: - bit function + FPGA status word: + bit function ========================================================================== - 15 SD DMA busy (0=idle, 1=busy) - 14 DAC read pointer MSB - 13 MSU read pointer MSB - 12 reserved (0) - 11 reserved (0) - 10 reserved (0) - 9 reserved (0) - 8 reserved (0) - 7 reserved (0) - 6 reserved (0) - 5 MSU1 Audio request from SNES - 4 MSU1 Data request from SNES - 3 reserved (0) - 2 MSU1 Audio control status: 0=no repeat, 1=repeat - 1 MSU1 Audio control status: 0=pause, 1=play - 0 MSU1 Audio control request + 15 SD DMA busy (0=idle, 1=busy) + 14 DAC read pointer MSB + 13 MSU read pointer MSB + 12 reserved (0) + 11 reserved (0) + 10 reserved (0) + 9 reserved (0) + 8 reserved (0) + 7 reserved (0) + 6 reserved (0) + 5 MSU1 Audio request from SNES + 4 MSU1 Data request from SNES + 3 reserved (0) + 2 MSU1 Audio control status: 0=no repeat, 1=repeat + 1 MSU1 Audio control status: 0=pause, 1=play + 0 MSU1 Audio control request - FPGA feature enable bits: - bit function + FPGA feature enable bits: + bit function ========================================================================== - 7 - - 6 - - 5 - - 4 enable $213F override - 3 enable MSU1 registers - 2 enable SRTC registers - 1 enable ST0010 mapping - 0 enable DSPx mapping + 7 - + 6 - + 5 - + 4 enable $213F override + 3 enable MSU1 registers + 2 enable SRTC registers + 1 enable ST0010 mapping + 0 enable DSPx mapping */ @@ -142,261 +142,292 @@ #include "timer.h" #include "sdnative.h" -void fpga_spi_init(void) { - spi_init(); - BITBAND(FPGA_MCU_RDY_REG->FIODIR, FPGA_MCU_RDY_BIT) = 0; +void fpga_spi_init( void ) +{ + spi_init(); + BITBAND( FPGA_MCU_RDY_REG->FIODIR, FPGA_MCU_RDY_BIT ) = 0; } -void set_msu_addr(uint16_t address) { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_SETADDR | FPGA_TGT_MSUBUF); - FPGA_TX_BYTE((address>>8)&0xff); - FPGA_TX_BYTE((address)&0xff); - FPGA_DESELECT(); +void set_msu_addr( uint16_t address ) +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_SETADDR | FPGA_TGT_MSUBUF ); + FPGA_TX_BYTE( ( address >> 8 ) & 0xff ); + FPGA_TX_BYTE( ( address ) & 0xff ); + FPGA_DESELECT(); } -void set_dac_addr(uint16_t address) { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_SETADDR | FPGA_TGT_DACBUF); - FPGA_TX_BYTE((address>>8)&0xff); - FPGA_TX_BYTE((address)&0xff); - FPGA_DESELECT(); +void set_dac_addr( uint16_t address ) +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_SETADDR | FPGA_TGT_DACBUF ); + FPGA_TX_BYTE( ( address >> 8 ) & 0xff ); + FPGA_TX_BYTE( ( address ) & 0xff ); + FPGA_DESELECT(); } -void set_mcu_addr(uint32_t address) { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_SETADDR | FPGA_TGT_MEM); - FPGA_TX_BYTE((address>>16)&0xff); - FPGA_TX_BYTE((address>>8)&0xff); - FPGA_TX_BYTE((address)&0xff); - FPGA_DESELECT(); +void set_mcu_addr( uint32_t address ) +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_SETADDR | FPGA_TGT_MEM ); + FPGA_TX_BYTE( ( address >> 16 ) & 0xff ); + FPGA_TX_BYTE( ( address >> 8 ) & 0xff ); + FPGA_TX_BYTE( ( address ) & 0xff ); + FPGA_DESELECT(); } -void set_saveram_mask(uint32_t mask) { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_SETRAMMASK); - FPGA_TX_BYTE((mask>>16)&0xff); - FPGA_TX_BYTE((mask>>8)&0xff); - FPGA_TX_BYTE((mask)&0xff); - FPGA_DESELECT(); +void set_saveram_mask( uint32_t mask ) +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_SETRAMMASK ); + FPGA_TX_BYTE( ( mask >> 16 ) & 0xff ); + FPGA_TX_BYTE( ( mask >> 8 ) & 0xff ); + FPGA_TX_BYTE( ( mask ) & 0xff ); + FPGA_DESELECT(); } -void set_rom_mask(uint32_t mask) { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_SETROMMASK); - FPGA_TX_BYTE((mask>>16)&0xff); - FPGA_TX_BYTE((mask>>8)&0xff); - FPGA_TX_BYTE((mask)&0xff); - FPGA_DESELECT(); +void set_rom_mask( uint32_t mask ) +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_SETROMMASK ); + FPGA_TX_BYTE( ( mask >> 16 ) & 0xff ); + FPGA_TX_BYTE( ( mask >> 8 ) & 0xff ); + FPGA_TX_BYTE( ( mask ) & 0xff ); + FPGA_DESELECT(); } -void set_mapper(uint8_t val) { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_SETMAPPER(val)); - FPGA_DESELECT(); +void set_mapper( uint8_t val ) +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_SETMAPPER( val ) ); + FPGA_DESELECT(); } -uint8_t fpga_test() { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_TEST); - uint8_t result = FPGA_RX_BYTE(); - FPGA_DESELECT(); - return result; +uint8_t fpga_test() +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_TEST ); + uint8_t result = FPGA_RX_BYTE(); + FPGA_DESELECT(); + return result; } -uint16_t fpga_status() { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_GETSTATUS); - uint16_t result = (FPGA_RX_BYTE()) << 8; - result |= FPGA_RX_BYTE(); - FPGA_DESELECT(); - return result; +uint16_t fpga_status() +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_GETSTATUS ); + uint16_t result = ( FPGA_RX_BYTE() ) << 8; + result |= FPGA_RX_BYTE(); + FPGA_DESELECT(); + return result; } -void fpga_set_sddma_range(uint16_t start, uint16_t end) { - printf("%s %08X -> %08X\n", __func__, start, end); - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_SDDMA_RANGE); - FPGA_TX_BYTE(start>>8); - FPGA_TX_BYTE(start&0xff); - FPGA_TX_BYTE(end>>8); - FPGA_TX_BYTE(end&0xff); - FPGA_DESELECT(); +void fpga_set_sddma_range( uint16_t start, uint16_t end ) +{ + printf( "%s %08X -> %08X\n", __func__, start, end ); + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_SDDMA_RANGE ); + FPGA_TX_BYTE( start >> 8 ); + FPGA_TX_BYTE( start & 0xff ); + FPGA_TX_BYTE( end >> 8 ); + FPGA_TX_BYTE( end & 0xff ); + FPGA_DESELECT(); } -void fpga_sddma(uint8_t tgt, uint8_t partial) { - //printf("%s %02X -> %02X\n", __func__, tgt, partial); - uint32_t test = 0; - uint8_t status = 0; - BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 0; - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_SDDMA | (tgt & 3) | (partial ? FPGA_SDDMA_PARTIAL : 0)); - FPGA_TX_BYTE(0x00); /* dummy for falling DMA_EN edge */ - FPGA_DESELECT(); - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_GETSTATUS); - DBG_SD printf("FPGA DMA request sent, wait for completion..."); - while(FPGA_RX_BYTE() & 0x80) { - FPGA_RX_BYTE(); /* eat the 2nd status byte */ - } - DBG_SD printf("...complete\n"); - FPGA_DESELECT(); - BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 1; +void fpga_sddma( uint8_t tgt, uint8_t partial ) +{ + //printf("%s %02X -> %02X\n", __func__, tgt, partial); + //uint32_t test = 0; + //uint8_t status = 0; + BITBAND( SD_CLKREG->FIODIR, SD_CLKPIN ) = 0; + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_SDDMA | ( tgt & 3 ) | ( partial ? FPGA_SDDMA_PARTIAL : 0 ) ); + FPGA_TX_BYTE( 0x00 ); /* dummy for falling DMA_EN edge */ + FPGA_DESELECT(); + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_GETSTATUS ); + DBG_SD printf( "FPGA DMA request sent, wait for completion..." ); + + while ( FPGA_RX_BYTE() & 0x80 ) + { + FPGA_RX_BYTE(); /* eat the 2nd status byte */ + } + + DBG_SD printf( "...complete\n" ); + FPGA_DESELECT(); + BITBAND( SD_CLKREG->FIODIR, SD_CLKPIN ) = 1; } -void dac_play() { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_DACPLAY); - FPGA_TX_BYTE(0x00); /* latch reset */ - FPGA_DESELECT(); +void dac_play() +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_DACPLAY ); + FPGA_TX_BYTE( 0x00 ); /* latch reset */ + FPGA_DESELECT(); } -void dac_pause() { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_DACPAUSE); - FPGA_TX_BYTE(0x00); /* latch reset */ - FPGA_DESELECT(); +void dac_pause() +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_DACPAUSE ); + FPGA_TX_BYTE( 0x00 ); /* latch reset */ + FPGA_DESELECT(); } -void dac_reset() { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_DACRESETPTR); - FPGA_TX_BYTE(0x00); /* latch reset */ - FPGA_TX_BYTE(0x00); /* latch reset */ - FPGA_DESELECT(); +void dac_reset() +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_DACRESETPTR ); + FPGA_TX_BYTE( 0x00 ); /* latch reset */ + FPGA_TX_BYTE( 0x00 ); /* latch reset */ + FPGA_DESELECT(); } -void msu_reset(uint16_t address) { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_MSUSETPTR); - FPGA_TX_BYTE((address>>8) & 0xff); /* address hi */ - FPGA_TX_BYTE(address & 0xff); /* address lo */ - FPGA_TX_BYTE(0x00); /* latch reset */ - FPGA_TX_BYTE(0x00); /* latch reset */ - FPGA_DESELECT(); +void msu_reset( uint16_t address ) +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_MSUSETPTR ); + FPGA_TX_BYTE( ( address >> 8 ) & 0xff ); /* address hi */ + FPGA_TX_BYTE( address & 0xff ); /* address lo */ + FPGA_TX_BYTE( 0x00 ); /* latch reset */ + FPGA_TX_BYTE( 0x00 ); /* latch reset */ + FPGA_DESELECT(); } -void set_msu_status(uint8_t set, uint8_t reset) { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_MSUSETBITS); - FPGA_TX_BYTE(set); - FPGA_TX_BYTE(reset); - FPGA_TX_BYTE(0x00); /* latch reset */ - FPGA_DESELECT(); +void set_msu_status( uint8_t set, uint8_t reset ) +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_MSUSETBITS ); + FPGA_TX_BYTE( set ); + FPGA_TX_BYTE( reset ); + FPGA_TX_BYTE( 0x00 ); /* latch reset */ + FPGA_DESELECT(); } -uint16_t get_msu_track() { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_MSUGETTRACK); - uint16_t result = (FPGA_RX_BYTE()) << 8; - result |= FPGA_RX_BYTE(); - FPGA_DESELECT(); - return result; +uint16_t get_msu_track() +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_MSUGETTRACK ); + uint16_t result = ( FPGA_RX_BYTE() ) << 8; + result |= FPGA_RX_BYTE(); + FPGA_DESELECT(); + return result; } -uint32_t get_msu_offset() { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_MSUGETADDR); - uint32_t result = (FPGA_RX_BYTE()) << 24; - result |= (FPGA_RX_BYTE()) << 16; - result |= (FPGA_RX_BYTE()) << 8; - result |= (FPGA_RX_BYTE()); - FPGA_DESELECT(); - return result; +uint32_t get_msu_offset() +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_MSUGETADDR ); + uint32_t result = ( FPGA_RX_BYTE() ) << 24; + result |= ( FPGA_RX_BYTE() ) << 16; + result |= ( FPGA_RX_BYTE() ) << 8; + result |= ( FPGA_RX_BYTE() ); + FPGA_DESELECT(); + return result; } -uint32_t get_snes_sysclk() { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_GETSYSCLK); - FPGA_TX_BYTE(0x00); /* dummy (copy current sysclk count to register) */ - uint32_t result = (FPGA_RX_BYTE()) << 24; - result |= (FPGA_RX_BYTE()) << 16; - result |= (FPGA_RX_BYTE()) << 8; - result |= (FPGA_RX_BYTE()); - FPGA_DESELECT(); - return result; +uint32_t get_snes_sysclk() +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_GETSYSCLK ); + FPGA_TX_BYTE( 0x00 ); /* dummy (copy current sysclk count to register) */ + uint32_t result = ( FPGA_RX_BYTE() ) << 24; + result |= ( FPGA_RX_BYTE() ) << 16; + result |= ( FPGA_RX_BYTE() ) << 8; + result |= ( FPGA_RX_BYTE() ); + FPGA_DESELECT(); + return result; } -void set_bsx_regs(uint8_t set, uint8_t reset) { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_BSXSETBITS); - FPGA_TX_BYTE(set); - FPGA_TX_BYTE(reset); - FPGA_TX_BYTE(0x00); /* latch reset */ - FPGA_DESELECT(); +void set_bsx_regs( uint8_t set, uint8_t reset ) +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_BSXSETBITS ); + FPGA_TX_BYTE( set ); + FPGA_TX_BYTE( reset ); + FPGA_TX_BYTE( 0x00 ); /* latch reset */ + FPGA_DESELECT(); } -void set_fpga_time(uint64_t time) { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_RTCSET); - FPGA_TX_BYTE((time >> 48) & 0xff); - FPGA_TX_BYTE((time >> 40) & 0xff); - FPGA_TX_BYTE((time >> 32) & 0xff); - FPGA_TX_BYTE((time >> 24) & 0xff); - FPGA_TX_BYTE((time >> 16) & 0xff); - FPGA_TX_BYTE((time >> 8) & 0xff); - FPGA_TX_BYTE(time & 0xff); - FPGA_TX_BYTE(0x00); - FPGA_DESELECT(); +void set_fpga_time( uint64_t time ) +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_RTCSET ); + FPGA_TX_BYTE( ( time >> 48 ) & 0xff ); + FPGA_TX_BYTE( ( time >> 40 ) & 0xff ); + FPGA_TX_BYTE( ( time >> 32 ) & 0xff ); + FPGA_TX_BYTE( ( time >> 24 ) & 0xff ); + FPGA_TX_BYTE( ( time >> 16 ) & 0xff ); + FPGA_TX_BYTE( ( time >> 8 ) & 0xff ); + FPGA_TX_BYTE( time & 0xff ); + FPGA_TX_BYTE( 0x00 ); + FPGA_DESELECT(); } -void fpga_reset_srtc_state() { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_SRTCRESET); - FPGA_TX_BYTE(0x00); - FPGA_TX_BYTE(0x00); - FPGA_DESELECT(); +void fpga_reset_srtc_state() +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_SRTCRESET ); + FPGA_TX_BYTE( 0x00 ); + FPGA_TX_BYTE( 0x00 ); + FPGA_DESELECT(); } -void fpga_reset_dspx_addr() { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_DSPRESETPTR); - FPGA_TX_BYTE(0x00); - FPGA_TX_BYTE(0x00); - FPGA_DESELECT(); +void fpga_reset_dspx_addr() +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_DSPRESETPTR ); + FPGA_TX_BYTE( 0x00 ); + FPGA_TX_BYTE( 0x00 ); + FPGA_DESELECT(); } -void fpga_write_dspx_pgm(uint32_t data) { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_DSPWRITEPGM); - FPGA_TX_BYTE((data>>16)&0xff); - FPGA_TX_BYTE((data>>8)&0xff); - FPGA_TX_BYTE((data)&0xff); - FPGA_TX_BYTE(0x00); - FPGA_TX_BYTE(0x00); - FPGA_DESELECT(); +void fpga_write_dspx_pgm( uint32_t data ) +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_DSPWRITEPGM ); + FPGA_TX_BYTE( ( data >> 16 ) & 0xff ); + FPGA_TX_BYTE( ( data >> 8 ) & 0xff ); + FPGA_TX_BYTE( ( data ) & 0xff ); + FPGA_TX_BYTE( 0x00 ); + FPGA_TX_BYTE( 0x00 ); + FPGA_DESELECT(); } -void fpga_write_dspx_dat(uint16_t data) { - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_DSPWRITEDAT); - FPGA_TX_BYTE((data>>8)&0xff); - FPGA_TX_BYTE((data)&0xff); - FPGA_TX_BYTE(0x00); - FPGA_TX_BYTE(0x00); - FPGA_DESELECT(); +void fpga_write_dspx_dat( uint16_t data ) +{ + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_DSPWRITEDAT ); + FPGA_TX_BYTE( ( data >> 8 ) & 0xff ); + FPGA_TX_BYTE( ( data ) & 0xff ); + FPGA_TX_BYTE( 0x00 ); + FPGA_TX_BYTE( 0x00 ); + FPGA_DESELECT(); } -void fpga_dspx_reset(uint8_t reset) { - FPGA_SELECT(); - FPGA_TX_BYTE(reset ? FPGA_CMD_DSPRESET : FPGA_CMD_DSPUNRESET); - FPGA_TX_BYTE(0x00); - FPGA_DESELECT(); +void fpga_dspx_reset( uint8_t reset ) +{ + FPGA_SELECT(); + FPGA_TX_BYTE( reset ? FPGA_CMD_DSPRESET : FPGA_CMD_DSPUNRESET ); + FPGA_TX_BYTE( 0x00 ); + FPGA_DESELECT(); } -void fpga_set_features(uint8_t feat) { - printf("set features: %02x\n", feat); - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_SETFEATURE); - FPGA_TX_BYTE(feat); - FPGA_DESELECT(); +void fpga_set_features( uint8_t feat ) +{ + printf( "set features: %02x\n", feat ); + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_SETFEATURE ); + FPGA_TX_BYTE( feat ); + FPGA_DESELECT(); } -void fpga_set_213f(uint8_t data) { - printf("set 213f: %d\n", data); - FPGA_SELECT(); - FPGA_TX_BYTE(FPGA_CMD_SET213F); - FPGA_TX_BYTE(data); - FPGA_DESELECT(); +void fpga_set_213f( uint8_t data ) +{ + printf( "set 213f: %d\n", data ); + FPGA_SELECT(); + FPGA_TX_BYTE( FPGA_CMD_SET213F ); + FPGA_TX_BYTE( data ); + FPGA_DESELECT(); } diff --git a/src/fpga_spi.h b/src/fpga_spi.h index 58cd065..42f19a7 100644 --- a/src/fpga_spi.h +++ b/src/fpga_spi.h @@ -32,13 +32,13 @@ #include "spi.h" #include "config.h" -#define FPGA_SS_BIT 16 -#define FPGA_SS_REG LPC_GPIO0 +#define FPGA_SS_BIT 16 +#define FPGA_SS_REG LPC_GPIO0 -#define FPGA_SELECT() do {FPGA_TX_SYNC(); BITBAND(FPGA_SS_REG->FIOCLR, FPGA_SS_BIT) = 1;} while (0) -#define FPGA_SELECT_ASYNC() do {BITBAND(FPGA_SS_REG->FIOCLR, FPGA_SS_BIT) = 1;} while (0) -#define FPGA_DESELECT() do {FPGA_TX_SYNC(); BITBAND(FPGA_SS_REG->FIOSET, FPGA_SS_BIT) = 1;} while (0) -#define FPGA_DESELECT_ASYNC() do {BITBAND(FPGA_SS_REG->FIOSET, FPGA_SS_BIT) = 1;} while (0) +#define FPGA_SELECT() do {FPGA_TX_SYNC(); BITBAND(FPGA_SS_REG->FIOCLR, FPGA_SS_BIT) = 1;} while (0) +#define FPGA_SELECT_ASYNC() do {BITBAND(FPGA_SS_REG->FIOCLR, FPGA_SS_BIT) = 1;} while (0) +#define FPGA_DESELECT() do {FPGA_TX_SYNC(); BITBAND(FPGA_SS_REG->FIOSET, FPGA_SS_BIT) = 1;} while (0) +#define FPGA_DESELECT_ASYNC() do {BITBAND(FPGA_SS_REG->FIOSET, FPGA_SS_BIT) = 1;} while (0) #define FPGA_TX_SYNC() spi_tx_sync() #define FPGA_TX_BYTE(x) spi_tx_byte(x) @@ -95,35 +95,35 @@ #define FPGA_CMD_GETSYSCLK (0xfe) #define FPGA_CMD_ECHO (0xff) -void fpga_spi_init(void); -uint8_t fpga_test(void); -uint16_t fpga_status(void); -void spi_fpga(void); -void spi_sd(void); -void spi_none(void); -void set_mcu_addr(uint32_t); -void set_dac_addr(uint16_t); -void dac_play(void); -void dac_pause(void); -void dac_reset(void); -void msu_reset(uint16_t); -void set_msu_addr(uint16_t); -void set_msu_status(uint8_t set, uint8_t reset); -void set_saveram_mask(uint32_t); -void set_rom_mask(uint32_t); -void set_mapper(uint8_t val); -void fpga_sddma(uint8_t tgt, uint8_t partial); -void fpga_set_sddma_range(uint16_t start, uint16_t end); -uint16_t get_msu_track(void); -uint32_t get_msu_offset(void); -uint32_t get_snes_sysclk(void); -void set_bsx_regs(uint8_t set, uint8_t reset); -void set_fpga_time(uint64_t time); -void fpga_reset_srtc_state(void); -void fpga_reset_dspx_addr(void); -void fpga_write_dspx_pgm(uint32_t data); -void fpga_write_dspx_dat(uint16_t data); -void fpga_dspx_reset(uint8_t reset); -void fpga_set_features(uint8_t feat); -void fpga_set_213f(uint8_t data); +void fpga_spi_init( void ); +uint8_t fpga_test( void ); +uint16_t fpga_status( void ); +void spi_fpga( void ); +void spi_sd( void ); +void spi_none( void ); +void set_mcu_addr( uint32_t ); +void set_dac_addr( uint16_t ); +void dac_play( void ); +void dac_pause( void ); +void dac_reset( void ); +void msu_reset( uint16_t ); +void set_msu_addr( uint16_t ); +void set_msu_status( uint8_t set, uint8_t reset ); +void set_saveram_mask( uint32_t ); +void set_rom_mask( uint32_t ); +void set_mapper( uint8_t val ); +void fpga_sddma( uint8_t tgt, uint8_t partial ); +void fpga_set_sddma_range( uint16_t start, uint16_t end ); +uint16_t get_msu_track( void ); +uint32_t get_msu_offset( void ); +uint32_t get_snes_sysclk( void ); +void set_bsx_regs( uint8_t set, uint8_t reset ); +void set_fpga_time( uint64_t time ); +void fpga_reset_srtc_state( void ); +void fpga_reset_dspx_addr( void ); +void fpga_write_dspx_pgm( uint32_t data ); +void fpga_write_dspx_dat( uint16_t data ); +void fpga_dspx_reset( uint8_t reset ); +void fpga_set_features( uint8_t feat ); +void fpga_set_213f( uint8_t data ); #endif diff --git a/src/irq.c b/src/irq.c index b4f3ee8..09940e6 100644 --- a/src/irq.c +++ b/src/irq.c @@ -4,12 +4,15 @@ #include "sdnative.h" #include "uart.h" -void EINT3_IRQHandler(void) { - NVIC_ClearPendingIRQ(EINT3_IRQn); - if(SD_CHANGE_DETECT) { - SD_CHANGE_CLR(); - sdn_changed(); - } +void EINT3_IRQHandler( void ) +{ + NVIC_ClearPendingIRQ( EINT3_IRQn ); + + if ( SD_CHANGE_DETECT ) + { + SD_CHANGE_CLR(); + sdn_changed(); + } } diff --git a/src/led.c b/src/led.c index 9fe5aea..124fb35 100644 --- a/src/led.c +++ b/src/led.c @@ -6,7 +6,7 @@ #include "led.h" #include "cli.h" -static uint8_t led_bright[16]={255,253,252,251,249,247,244,239,232,223,210,191,165,127,74,0}; +static uint8_t led_bright[16] = {255, 253, 252, 251, 249, 247, 244, 239, 232, 223, 210, 191, 165, 127, 74, 0}; int led_rdyledstate = 0; int led_readledstate = 0; @@ -22,127 +22,156 @@ int led_pwmstate = 0; write red P1.23 PWM1[4] */ -void rdyled(unsigned int state) { - if(led_pwmstate) { - rdybright(state?15:0); - } else { - BITBAND(LPC_GPIO2->FIODIR, 4) = state; - } - led_rdyledstate = state; +void rdyled( unsigned int state ) +{ + if ( led_pwmstate ) + { + rdybright( state ? 15 : 0 ); + } + else + { + BITBAND( LPC_GPIO2->FIODIR, 4 ) = state; + } + + led_rdyledstate = state; } -void readled(unsigned int state) { - if(led_pwmstate) { - readbright(state?15:0); - } else { - BITBAND(LPC_GPIO2->FIODIR, 5) = state; - } - led_readledstate = state; +void readled( unsigned int state ) +{ + if ( led_pwmstate ) + { + readbright( state ? 15 : 0 ); + } + else + { + BITBAND( LPC_GPIO2->FIODIR, 5 ) = state; + } + + led_readledstate = state; } -void writeled(unsigned int state) { - if(led_pwmstate) { - writebright(state?15:0); - } else { - BITBAND(LPC_GPIO1->FIODIR, 23) = state; - } - led_writeledstate = state; +void writeled( unsigned int state ) +{ + if ( led_pwmstate ) + { + writebright( state ? 15 : 0 ); + } + else + { + BITBAND( LPC_GPIO1->FIODIR, 23 ) = state; + } + + led_writeledstate = state; } -void rdybright(uint8_t bright) { - LPC_PWM1->MR5 = led_bright[(bright & 15)]; - BITBAND(LPC_PWM1->LER, 5) = 1; +void rdybright( uint8_t bright ) +{ + LPC_PWM1->MR5 = led_bright[( bright & 15 )]; + BITBAND( LPC_PWM1->LER, 5 ) = 1; } -void readbright(uint8_t bright) { - LPC_PWM1->MR6 = led_bright[(bright & 15)]; - BITBAND(LPC_PWM1->LER, 6) = 1; +void readbright( uint8_t bright ) +{ + LPC_PWM1->MR6 = led_bright[( bright & 15 )]; + BITBAND( LPC_PWM1->LER, 6 ) = 1; } -void writebright(uint8_t bright) { - LPC_PWM1->MR4 = led_bright[(bright & 15)]; - BITBAND(LPC_PWM1->LER, 4) = 1; +void writebright( uint8_t bright ) +{ + LPC_PWM1->MR4 = led_bright[( bright & 15 )]; + BITBAND( LPC_PWM1->LER, 4 ) = 1; } -void led_clkout32(uint32_t val) { - while(1) { - rdyled(1); - delay_ms(400); - readled((val & BV(31))>>31); - rdyled(0); - val<<=1; - delay_ms(400); - } +void led_clkout32( uint32_t val ) +{ + while ( 1 ) + { + rdyled( 1 ); + delay_ms( 400 ); + readled( ( val & BV( 31 ) ) >> 31 ); + rdyled( 0 ); + val <<= 1; + delay_ms( 400 ); + } } -void toggle_rdy_led() { - rdyled(~led_rdyledstate); +void toggle_rdy_led() +{ + rdyled( ~led_rdyledstate ); } -void toggle_read_led() { - readled(~led_readledstate); +void toggle_read_led() +{ + readled( ~led_readledstate ); } -void toggle_write_led() { - writeled(~led_writeledstate); +void toggle_write_led() +{ + writeled( ~led_writeledstate ); } -void led_panic() { - led_std(); - while(1) { - rdyled(1); - readled(1); - writeled(1); - delay_ms(100); - rdyled(0); - readled(0); - writeled(0); - delay_ms(100); - cli_entrycheck(); - } +void led_panic() +{ + led_std(); + + while ( 1 ) + { + rdyled( 1 ); + readled( 1 ); + writeled( 1 ); + delay_ms( 100 ); + rdyled( 0 ); + readled( 0 ); + writeled( 0 ); + delay_ms( 100 ); + cli_entrycheck(); + } } -void led_pwm() { -/* Rev.C P2.4, P2.5, P1.23 */ - BITBAND(LPC_PINCON->PINSEL4, 9) = 0; - BITBAND(LPC_PINCON->PINSEL4, 8) = 1; +void led_pwm() +{ + /* Rev.C P2.4, P2.5, P1.23 */ + BITBAND( LPC_PINCON->PINSEL4, 9 ) = 0; + BITBAND( LPC_PINCON->PINSEL4, 8 ) = 1; - BITBAND(LPC_PINCON->PINSEL4, 11) = 0; - BITBAND(LPC_PINCON->PINSEL4, 10) = 1; + BITBAND( LPC_PINCON->PINSEL4, 11 ) = 0; + BITBAND( LPC_PINCON->PINSEL4, 10 ) = 1; - BITBAND(LPC_PINCON->PINSEL3, 15) = 1; - BITBAND(LPC_PINCON->PINSEL3, 14) = 0; + BITBAND( LPC_PINCON->PINSEL3, 15 ) = 1; + BITBAND( LPC_PINCON->PINSEL3, 14 ) = 0; - BITBAND(LPC_PWM1->PCR, 12) = 1; - BITBAND(LPC_PWM1->PCR, 13) = 1; - BITBAND(LPC_PWM1->PCR, 14) = 1; + BITBAND( LPC_PWM1->PCR, 12 ) = 1; + BITBAND( LPC_PWM1->PCR, 13 ) = 1; + BITBAND( LPC_PWM1->PCR, 14 ) = 1; - led_pwmstate = 1; + led_pwmstate = 1; } -void led_std() { - BITBAND(LPC_PINCON->PINSEL4, 9) = 0; - BITBAND(LPC_PINCON->PINSEL4, 8) = 0; +void led_std() +{ + BITBAND( LPC_PINCON->PINSEL4, 9 ) = 0; + BITBAND( LPC_PINCON->PINSEL4, 8 ) = 0; - BITBAND(LPC_PINCON->PINSEL4, 11) = 0; - BITBAND(LPC_PINCON->PINSEL4, 10) = 0; + BITBAND( LPC_PINCON->PINSEL4, 11 ) = 0; + BITBAND( LPC_PINCON->PINSEL4, 10 ) = 0; - BITBAND(LPC_PINCON->PINSEL3, 15) = 0; - BITBAND(LPC_PINCON->PINSEL3, 14) = 0; + BITBAND( LPC_PINCON->PINSEL3, 15 ) = 0; + BITBAND( LPC_PINCON->PINSEL3, 14 ) = 0; - BITBAND(LPC_PWM1->PCR, 12) = 0; - BITBAND(LPC_PWM1->PCR, 13) = 0; - BITBAND(LPC_PWM1->PCR, 14) = 0; + BITBAND( LPC_PWM1->PCR, 12 ) = 0; + BITBAND( LPC_PWM1->PCR, 13 ) = 0; + BITBAND( LPC_PWM1->PCR, 14 ) = 0; - led_pwmstate = 0; + led_pwmstate = 0; } -void led_init() { -/* power is already connected by default */ -/* set PCLK divider to 8 */ - BITBAND(LPC_SC->PCLKSEL0, 13) = 1; - BITBAND(LPC_SC->PCLKSEL0, 12) = 1; - LPC_PWM1->MR0 = 255; - BITBAND(LPC_PWM1->LER, 0) = 1; - BITBAND(LPC_PWM1->TCR, 0) = 1; - BITBAND(LPC_PWM1->TCR, 3) = 1; - BITBAND(LPC_PWM1->MCR, 1) = 1; +void led_init() +{ + /* power is already connected by default */ + /* set PCLK divider to 8 */ + BITBAND( LPC_SC->PCLKSEL0, 13 ) = 1; + BITBAND( LPC_SC->PCLKSEL0, 12 ) = 1; + LPC_PWM1->MR0 = 255; + BITBAND( LPC_PWM1->LER, 0 ) = 1; + BITBAND( LPC_PWM1->TCR, 0 ) = 1; + BITBAND( LPC_PWM1->TCR, 3 ) = 1; + BITBAND( LPC_PWM1->MCR, 1 ) = 1; } diff --git a/src/lpc1754.cfg b/src/lpc1754.cfg index fa34d17..1109b77 100644 --- a/src/lpc1754.cfg +++ b/src/lpc1754.cfg @@ -27,8 +27,8 @@ if { [info exists CPUTAPID ] } { #delays on reset lines #if your OpenOCD version rejects "jtag_nsrst_delay" replace it with: -#adapter_nsrst_delay 200 -jtag_nsrst_delay 200 +adapter_nsrst_delay 200 +#jtag_nsrst_delay 200 jtag_ntrst_delay 200 # LPC2000 & LPC1700 -> SRST causes TRST @@ -39,7 +39,8 @@ jtag newtap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID #jtag newtap x3s tap -irlen 6 -ircapture 0x11 -irmask 0x11 -expected-id 0x0141c093 set _TARGETNAME $_CHIPNAME.cpu -target create $_TARGETNAME cortex_m3 -chain-position $_TARGETNAME -event reset-init 0 +#target create $_TARGETNAME cortex_m3 -chain-position $_TARGETNAME -event reset-init 0 +target create $_TARGETNAME cortex_m -chain-position $_TARGETNAME -event reset-init 0 # LPC1754 has 16kB of SRAM In the ARMv7-M "Code" area (at 0x10000000) # and 16K more on AHB, in the ARMv7-M "SRAM" area, (at 0x2007c000). @@ -56,7 +57,7 @@ flash bank $_FLASHNAME lpc2000 0x0 0x20000 0 0 $_TARGETNAME \ # Run with *real slow* clock by default since the # boot rom could have been playing with the PLL, so # we have no idea what clock the target is running at. -jtag_khz 1000 +adapter_khz 1000 $_TARGETNAME configure -event reset-init { # Do not remap 0x0000-0x0020 to anything but the flash (i.e. select diff --git a/src/main.c b/src/main.c index e72b091..f375de5 100644 --- a/src/main.c +++ b/src/main.c @@ -29,8 +29,8 @@ #include "sysinfo.h" #include "cfg.h" -#define EMC0TOGGLE (3<<4) -#define MR0R (1<<1) +#define EMC0TOGGLE (3<<4) +#define MR0R (1<<1) int i; @@ -50,318 +50,413 @@ extern volatile cfg_t CFG; enum system_states { - SYS_RTC_STATUS = 0, - SYS_LAST_STATUS = 1 + SYS_RTC_STATUS = 0, + SYS_LAST_STATUS = 1 }; -int main(void) +int main( void ) { - LPC_GPIO2->FIODIR = BV(4) | BV(5); - LPC_GPIO1->FIODIR = BV(23) | BV(SNES_CIC_PAIR_BIT); - BITBAND(SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT) = 1; - LPC_GPIO0->FIODIR = BV(16); - - /* connect UART3 on P0[25:26] + SSP0 on P0[15:18] + MAT3.0 on P0[10] */ - LPC_PINCON->PINSEL1 = BV(18) | BV(19) | BV(20) | BV(21) /* UART3 */ - | BV(3) | BV(5); /* SSP0 (FPGA) except SS */ - LPC_PINCON->PINSEL0 = BV(31); /* SSP0 */ -/* | BV(13) | BV(15) | BV(17) | BV(19) SSP1 (SD) */ - - /* pull-down CIC data lines */ - LPC_PINCON->PINMODE0 = BV(0) | BV(1) | BV(2) | BV(3); - - clock_disconnect(); - snes_init(); - snes_reset(1); - power_init(); - timer_init(); - uart_init(); - fpga_spi_init(); - spi_preinit(); - led_init(); - /* do this last because the peripheral init()s change PCLK dividers */ - clock_init(); - LPC_PINCON->PINSEL0 |= BV(20) | BV(21); /* MAT3.0 (FPGA clock) */ -led_pwm(); - sdn_init(); - printf("\n\nsd2snes mk.2\n============\nfw ver.: " CONFIG_VERSION "\ncpu clock: %d Hz\n", CONFIG_CPU_FREQUENCY); -printf("PCONP=%lx\n", LPC_SC->PCONP); - - file_init(); - cic_init(0); -/* setup timer (fpga clk) */ - LPC_TIM3->TCR=2; - LPC_TIM3->CTCR=0; - LPC_TIM3->PR=0; - LPC_TIM3->EMR=EMC0TOGGLE; - LPC_TIM3->MCR=MR0R; - LPC_TIM3->MR0=1; - LPC_TIM3->TCR=1; - fpga_init(); - fpga_rompgm(); - sram_writebyte(0, SRAM_CMD_ADDR); - while(1) { - if(disk_state == DISK_CHANGED) { - sdn_init(); - newcard = 1; - } - load_bootrle(SRAM_MENU_ADDR); - set_saveram_mask(0x1fff); - set_rom_mask(0x3fffff); - set_mapper(0x7); - snes_reset(0); - while(get_cic_state() == CIC_FAIL) { - rdyled(0); - readled(0); - writeled(0); - delay_ms(500); - rdyled(1); - readled(1); - writeled(1); - delay_ms(500); - } - /* some sanity checks */ uint8_t card_go = 0; - while(!card_go) { - if(disk_status(0) & (STA_NOINIT|STA_NODISK)) - { - snes_bootprint(" No SD Card found! \0"); - while(disk_status(0) & (STA_NOINIT|STA_NODISK)); - delay_ms(200); - } - file_open((uint8_t*)"/sd2snes/menu.bin", FA_READ); - if(file_status != FILE_OK) - { - snes_bootprint(" /sd2snes/menu.bin not found! \0"); - while(disk_status(0) == RES_OK); - } - else - { - card_go = 1; - } - file_close(); - } - snes_bootprint(" Loading ... \0"); - if(get_cic_state() == CIC_PAIR) { - printf("PAIR MODE ENGAGED!\n"); - cic_pair(CIC_NTSC, CIC_NTSC); - } - rdyled(1); - readled(0); - writeled(0); - - cfg_load(); - cfg_save(); - sram_writebyte(cfg_is_last_game_valid(), SRAM_STATUS_ADDR+SYS_LAST_STATUS); - cfg_get_last_game(file_lfn); - sram_writeblock(strrchr((const char*)file_lfn, '/')+1, SRAM_LASTGAME_ADDR, 256); - *fs_path=0; uint32_t saved_dir_id; - get_db_id(&saved_dir_id); - - uint32_t mem_dir_id = sram_readlong(SRAM_DIRID); - uint32_t mem_magic = sram_readlong(SRAM_SCRATCHPAD); - printf("mem_magic=%lx mem_dir_id=%lx saved_dir_id=%lx\n", mem_magic, mem_dir_id, saved_dir_id); - if((mem_magic != 0x12345678) || (mem_dir_id != saved_dir_id) || (newcard)) { - newcard = 0; - /* generate fs footprint (interesting files only) */ - uint32_t curr_dir_id = scan_dir(fs_path, NULL, 0, 0); - printf("curr dir id = %lx\n", curr_dir_id); - /* files changed or no database found? */ - if((get_db_id(&saved_dir_id) != FR_OK) - || saved_dir_id != curr_dir_id) { - /* rebuild database */ - printf("saved dir id = %lx\n", saved_dir_id); - printf("rebuilding database..."); - snes_bootprint(" rebuilding database ... \0"); - curr_dir_id = scan_dir(fs_path, NULL, 1, 0); - sram_writeblock(&curr_dir_id, SRAM_DB_ADDR, 4); - uint32_t endaddr, direndaddr; - sram_readblock(&endaddr, SRAM_DB_ADDR+4, 4); - sram_readblock(&direndaddr, SRAM_DB_ADDR+8, 4); - printf("%lx %lx\n", endaddr, direndaddr); - printf("sorting database..."); - snes_bootprint(" sorting database ... \0"); - sort_all_dir(direndaddr); - printf("done\n"); - snes_bootprint(" saving database ... \0"); - save_sram((uint8_t*)"/sd2snes/sd2snes.db", endaddr-SRAM_DB_ADDR, SRAM_DB_ADDR); - save_sram((uint8_t*)"/sd2snes/sd2snes.dir", direndaddr-(SRAM_DIR_ADDR), SRAM_DIR_ADDR); - fpga_pgm((uint8_t*)"/sd2snes/fpga_base.bit"); - printf("done\n"); - } else { - printf("saved dir id = %lx\n", saved_dir_id); - printf("different card, consistent db, loading db...\n"); - fpga_pgm((uint8_t*)"/sd2snes/fpga_base.bit"); - load_sram_offload((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR); - load_sram_offload((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR); - } - sram_writelong(curr_dir_id, SRAM_DIRID); - sram_writelong(0x12345678, SRAM_SCRATCHPAD); - } else { - snes_bootprint(" same card, loading db... \0"); - printf("same card, loading db...\n"); - fpga_pgm((uint8_t*)"/sd2snes/fpga_base.bit"); - load_sram_offload((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR); - load_sram_offload((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR); - } - /* cli_loop(); */ - /* load menu */ - - fpga_dspx_reset(1); - uart_putc('('); - load_rom((uint8_t*)"/sd2snes/menu.bin", SRAM_MENU_ADDR, 0); - /* force memory size + mapper */ - set_rom_mask(0x3fffff); - set_mapper(0x7); - uart_putc(')'); - uart_putcrlf(); - - sram_writebyte(0, SRAM_CMD_ADDR); - - if((rtc_state = rtc_isvalid()) != RTC_OK) { - printf("RTC invalid!\n"); - sram_writebyte(0xff, SRAM_STATUS_ADDR+SYS_RTC_STATUS); - set_bcdtime(0x20120701000000LL); - set_fpga_time(0x20120701000000LL); - invalidate_rtc(); - } else { - printf("RTC valid!\n"); - sram_writebyte(0x00, SRAM_STATUS_ADDR+SYS_RTC_STATUS); - set_fpga_time(get_bcdtime()); - } - sram_memset(SRAM_SYSINFO_ADDR, 13*40, 0x20); - printf("SNES GO!\n"); - snes_reset(1); - fpga_reset_srtc_state(); - delay_ms(SNES_RESET_PULSELEN_MS); - sram_writebyte(32, SRAM_CMD_ADDR); - snes_reset(0); - + uint32_t mem_dir_id; + uint32_t mem_magic; uint8_t cmd = 0; uint64_t btime = 0; - uint32_t filesize=0; - printf("test sram\n"); - while(!sram_reliable()) cli_entrycheck(); - printf("ok\n"); -//while(1) { -// delay_ms(1000); -// printf("Estimated SNES master clock: %ld Hz\n", get_snes_sysclk()); -//} - //sram_hexdump(SRAM_DB_ADDR, 0x200); - //sram_hexdump(SRAM_MENU_ADDR, 0x400); - while(!cmd) { - cmd=menu_main_loop(); - printf("cmd: %d\n", cmd); - uart_putc('-'); - switch(cmd) { - case SNES_CMD_LOADROM: - get_selected_name(file_lfn); - printf("Selected name: %s\n", file_lfn); - cfg_save_last_game(file_lfn); - cfg_set_last_game_valid(1); - cfg_save(); - filesize = load_rom(file_lfn, SRAM_ROM_ADDR, LOADROM_WITH_SRAM | LOADROM_WITH_RESET); - printf("Filesize = %lu\n", filesize); - break; - case SNES_CMD_SETRTC: - /* get time from RAM */ - btime = sram_gettime(SRAM_PARAM_ADDR); - /* set RTC */ - set_bcdtime(btime); - set_fpga_time(btime); - cmd=0; /* stay in menu loop */ - break; - case SNES_CMD_SYSINFO: - /* go to sysinfo loop */ - sysinfo_loop(); - cmd=0; /* stay in menu loop */ - break; - case SNES_CMD_LOADSPC: - /* load SPC file */ - get_selected_name(file_lfn); - printf("Selected name: %s\n", file_lfn); - filesize = load_spc(file_lfn, SRAM_SPC_DATA_ADDR, SRAM_SPC_HEADER_ADDR); - cmd=0; /* stay in menu loop */ - break; - case SNES_CMD_RESET: - /* process RESET request from SNES */ - printf("RESET requested by SNES\n"); - snes_reset_pulse(); - cmd=0; /* stay in menu loop */ - break; - case SNES_CMD_LOADLAST: - cfg_get_last_game(file_lfn); - printf("Selected name: %s\n", file_lfn); - filesize = load_rom(file_lfn, SRAM_ROM_ADDR, LOADROM_WITH_SRAM | LOADROM_WITH_RESET); - break; - default: - printf("unknown cmd: %d\n", cmd); - cmd=0; /* unknown cmd: stay in loop */ - break; - } - } - printf("loaded %lu bytes\n", filesize); - printf("cmd was %x, going to snes main loop\n", cmd); + uint32_t filesize = 0; + uint8_t snes_reset_prev = 0, snes_reset_now = 0, snes_reset_state = 0; + uint16_t reset_count = 0; - if(romprops.has_msu1) { - while(!msu1_loop()); - prepare_reset(); - continue; - } + LPC_GPIO2->FIODIR = BV( 4 ) | BV( 5 ); + LPC_GPIO1->FIODIR = BV( 23 ) | BV( SNES_CIC_PAIR_BIT ); + BITBAND( SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT ) = 1; + LPC_GPIO0->FIODIR = BV( 16 ); - cmd=0; - uint8_t snes_reset_prev=0, snes_reset_now=0, snes_reset_state=0; - uint16_t reset_count=0; - while(fpga_test() == FPGA_TEST_TOKEN) + /* connect UART3 on P0[25:26] + SSP0 on P0[15:18] + MAT3.0 on P0[10] */ + LPC_PINCON->PINSEL1 = BV( 18 ) | BV( 19 ) | BV( 20 ) | BV( 21 ) /* UART3 */ + | BV( 3 ) | BV( 5 ); /* SSP0 (FPGA) except SS */ + LPC_PINCON->PINSEL0 = BV( 31 ); /* SSP0 */ + /* | BV(13) | BV(15) | BV(17) | BV(19) SSP1 (SD) */ + + /* pull-down CIC data lines */ + LPC_PINCON->PINMODE0 = BV( 0 ) | BV( 1 ) | BV( 2 ) | BV( 3 ); + + clock_disconnect(); /* Disable clock */ + snes_init(); /* Set SNES Reset */ + power_init(); /* Enable power block of LPC */ + timer_init(); /* Enable internal timer */ + uart_init(); /* Configure UART */ + fpga_spi_init(); /* Configure FPGA_SPI IOs */ + spi_preinit(); /* Initialise SPI IO */ + led_init(); /* Initialise LEDs IO */ + + + /* do this last because the peripheral init()s change PCLK dividers */ + clock_init(); + /* Output FPGA clock */ + LPC_PINCON->PINSEL0 |= BV( 20 ) | BV( 21 ); /* MAT3.0 (FPGA clock) */ + + led_pwm(); /* Enabke PWM on LED (even if not used...) */ + sdn_init(); /* SD init */ + + /* Print banner */ + printf( "\n\nsd2snes mk.2\n============\nfw ver.: " CONFIG_VERSION "\ncpu clock: %d Hz\n", CONFIG_CPU_FREQUENCY ); + + /* Init file manager */ + file_init(); + + /* */ + cic_init( 0 ); + + /* setup timer (fpga clk) */ + LPC_TIM3->TCR = 2; + LPC_TIM3->CTCR = 0; + LPC_TIM3->PR = 0; + LPC_TIM3->EMR = EMC0TOGGLE; + LPC_TIM3->MCR = MR0R; + LPC_TIM3->MR0 = 1; + LPC_TIM3->TCR = 1; + + fpga_init(); + fpga_rompgm(); + sram_writebyte( 0, SRAM_CMD_ADDR ); + + while ( 1 ) /* Main loop */ { - cli_entrycheck(); - sleep_ms(250); - sram_reliable(); - printf("%s ", get_cic_statename(get_cic_state())); - if(reset_changed) - { - printf("reset\n"); - reset_changed = 0; + if ( disk_state == DISK_CHANGED ) + { + sdn_init(); /* Reinit SD card */ + newcard = 1; + } + + load_bootrle( SRAM_MENU_ADDR ); + set_saveram_mask( 0xffff ); + set_rom_mask( 0x3fffff ); + set_mapper( 0x7 ); + snes_reset( 0 ); + + while ( get_cic_state() == CIC_FAIL ) + { + rdyled( 0 ); + readled( 0 ); + writeled( 0 ); + delay_ms( 500 ); + rdyled( 1 ); + readled( 1 ); + writeled( 1 ); + delay_ms( 500 ); + } + + /* Wait for valid card inserted */ + card_go = 0; + + while ( !card_go ) + { + if ( disk_status( 0 ) & ( STA_NOINIT | STA_NODISK ) ) + { + snes_bootprint( " No SD Card found! \0" ); + + while ( disk_status( 0 ) & ( STA_NOINIT | STA_NODISK ) ); + + delay_ms( 200 ); + } + + file_open( ( uint8_t * )"/sd2snes/menu.bin", FA_READ ); + + if ( file_status != FILE_OK ) + { + snes_bootprint( " /sd2snes/menu.bin not found! \0" ); + + while ( disk_status( 0 ) == RES_OK ); + } + else + { + /* Card found ! */ + card_go = 1; + } + + file_close(); + } + + snes_bootprint( " Loading ... \0" ); + + if ( get_cic_state() == CIC_PAIR ) + { + printf( "PAIR MODE ENGAGED!\n" ); + cic_pair( CIC_NTSC, CIC_NTSC ); + } + + rdyled( 1 ); + readled( 0 ); + writeled( 0 ); + + /* Load user config */ + cfg_load(); + cfg_save(); + + sram_writebyte( cfg_is_last_game_valid(), SRAM_STATUS_ADDR + SYS_LAST_STATUS ); + + cfg_get_last_game( file_lfn ); + sram_writeblock( strrchr( ( const char * )file_lfn, '/' ) + 1, SRAM_LASTGAME_ADDR, 256 ); + + *fs_path = 0; + + get_db_id( &saved_dir_id ); + + mem_dir_id = sram_readlong( SRAM_DIRID ); + mem_magic = sram_readlong( SRAM_SCRATCHPAD ); + + printf( "mem_magic=%lx mem_dir_id=%lx saved_dir_id=%lx\n", mem_magic, mem_dir_id, saved_dir_id ); + + if ( ( mem_magic != 0x12345678 ) || ( mem_dir_id != saved_dir_id ) || ( newcard ) ) + { + newcard = 0; + /* generate fs footprint (interesting files only) */ + uint32_t curr_dir_id = scan_dir( fs_path, NULL, 0, 0 ); + + printf( "curr dir id = %lx\n", curr_dir_id ); + + /* files changed or no database found? */ + if ( ( get_db_id( &saved_dir_id ) != FR_OK ) || saved_dir_id != curr_dir_id ) + { + uint32_t endaddr, direndaddr; + /* rebuild database */ + printf( "saved dir id = %lx\n", saved_dir_id ); + printf( "rebuilding database..." ); + snes_bootprint( " rebuilding database ... \0" ); + curr_dir_id = scan_dir( fs_path, NULL, 1, 0 ); + sram_writeblock( &curr_dir_id, SRAM_DB_ADDR, 4 ); + sram_readblock( &endaddr, SRAM_DB_ADDR + 4, 4 ); + sram_readblock( &direndaddr, SRAM_DB_ADDR + 8, 4 ); + printf( "%lx %lx\n", endaddr, direndaddr ); + printf( "sorting database..." ); + snes_bootprint( " sorting database ... \0" ); + sort_all_dir( direndaddr ); + printf( "done\n" ); + snes_bootprint( " saving database ... \0" ); + save_sram( ( uint8_t * )"/sd2snes/sd2snes.db", endaddr - SRAM_DB_ADDR, SRAM_DB_ADDR ); + save_sram( ( uint8_t * )"/sd2snes/sd2snes.dir", direndaddr - ( SRAM_DIR_ADDR ), SRAM_DIR_ADDR ); + fpga_pgm( ( uint8_t * )"/sd2snes/fpga_base.bit" ); + printf( "done\n" ); + } + else + { + printf( "saved dir id = %lx\n", saved_dir_id ); + printf( "different card, consistent db, loading db...\n" ); + fpga_pgm( ( uint8_t * )"/sd2snes/fpga_base.bit" ); + load_sram_offload( ( uint8_t * )"/sd2snes/sd2snes.db", SRAM_DB_ADDR ); + load_sram_offload( ( uint8_t * )"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR ); + } + + sram_writelong( curr_dir_id, SRAM_DIRID ); + sram_writelong( 0x12345678, SRAM_SCRATCHPAD ); + } + else + { + snes_bootprint( " same card, loading db... \n" ); + fpga_pgm( ( uint8_t * )"/sd2snes/fpga_base.bit" ); + load_sram_offload( ( uint8_t * )"/sd2snes/sd2snes.db", SRAM_DB_ADDR ); + load_sram_offload( ( uint8_t * )"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR ); + } + + /* cli_loop(); */ + /* load menu */ + + fpga_dspx_reset( 1 ); + uart_putc( '(' ); + uart_putcrlf(); + load_rom( ( uint8_t * )"/sd2snes/menu.bin", SRAM_MENU_ADDR, 0 ); + /* force memory size + mapper */ + set_rom_mask( 0x3fffff ); + set_mapper( 0x7 ); + uart_putc( ')' ); + uart_putcrlf(); + + sram_writebyte( 0, SRAM_CMD_ADDR ); + + snes_bootprint( " same card, loading db... \n" ); + + + if ( ( rtc_state = rtc_isvalid() ) != RTC_OK ) + { + printf( "RTC invalid!\n" ); + sram_writebyte( 0xff, SRAM_STATUS_ADDR + SYS_RTC_STATUS ); + set_bcdtime( 0x20120701000000LL ); + set_fpga_time( 0x20120701000000LL ); + invalidate_rtc(); + } + else + { + printf( "RTC valid!\n" ); + sram_writebyte( 0x00, SRAM_STATUS_ADDR + SYS_RTC_STATUS ); + set_fpga_time( get_bcdtime() ); + } + + sram_memset( SRAM_SYSINFO_ADDR, 13 * 40, 0x20 ); + printf( "SNES GO!\n" ); + snes_reset( 1 ); fpga_reset_srtc_state(); - } - snes_reset_now = get_snes_reset(); - if (snes_reset_now) - { - if (!snes_reset_prev) + delay_ms( SNES_RESET_PULSELEN_MS ); + sram_writebyte( 32, SRAM_CMD_ADDR ); + snes_reset( 0 ); + + cmd = 0; + btime = 0; + filesize = 0; + + printf( "test sram... " ); + + while ( !sram_reliable() ) { - printf("RESET BUTTON DOWN\n"); - snes_reset_state = 1; - reset_count = 0; + cli_entrycheck(); } - } - else - { - if (snes_reset_prev) + + printf( "ok\nWaiting command from menu...\n" ); + + //while(1) { + // delay_ms(1000); + // printf("Estimated SNES master clock: %ld Hz\n", get_snes_sysclk()); + //} + //sram_hexdump(SRAM_DB_ADDR, 0x200); + //sram_hexdump(SRAM_MENU_ADDR, 0x400); + + while ( !cmd ) { - printf("RESET BUTTON UP\n"); - snes_reset_state = 0; + cmd = menu_main_loop(); + printf( "cmd: %d\n", cmd ); + + switch ( cmd ) + { + case SNES_CMD_LOADROM: + get_selected_name( file_lfn ); + printf( "Selected name: %s\n", file_lfn ); + cfg_save_last_game( file_lfn ); + cfg_set_last_game_valid( 1 ); + cfg_save(); + filesize = load_rom( file_lfn, SRAM_ROM_ADDR, LOADROM_WITH_SRAM | LOADROM_WITH_RESET ); + printf( "Filesize = %lu\n", filesize ); + break; + + case SNES_CMD_SETRTC: + /* get time from RAM */ + btime = sram_gettime( SRAM_PARAM_ADDR ); + /* set RTC */ + set_bcdtime( btime ); + set_fpga_time( btime ); + cmd = 0; /* stay in menu loop */ + break; + + case SNES_CMD_SYSINFO: + /* go to sysinfo loop */ + sysinfo_loop(); + cmd = 0; /* stay in menu loop */ + break; + + case SNES_CMD_LOADSPC: + /* load SPC file */ + get_selected_name( file_lfn ); + printf( "Selected name: %s\n", file_lfn ); + filesize = load_spc( file_lfn, SRAM_SPC_DATA_ADDR, SRAM_SPC_HEADER_ADDR ); + cmd = 0; /* stay in menu loop */ + break; + + case SNES_CMD_RESET: + /* process RESET request from SNES */ + printf( "RESET requested by SNES\n" ); + snes_reset_pulse(); + cmd = 0; /* stay in menu loop */ + break; + + case SNES_CMD_LOADLAST: + cfg_get_last_game( file_lfn ); + printf( "Selected name: %s\n", file_lfn ); + filesize = load_rom( file_lfn, SRAM_ROM_ADDR, LOADROM_WITH_SRAM | LOADROM_WITH_RESET ); + break; + + default: + printf( "unknown cmd: %d\n", cmd ); + cmd = 0; /* unknown cmd: stay in loop */ + break; + } } - } - if (snes_reset_state) - { - reset_count++; - } else { - sram_reliable(); - snes_main_loop(); - } - if(reset_count>4) { - reset_count=0; - prepare_reset(); - break; - } - snes_reset_prev = snes_reset_now; + + printf( "loaded %lu bytes\n", filesize ); + printf( "cmd was %x, going to snes main loop\n", cmd ); + + if ( romprops.has_msu1 ) + { + while ( !msu1_loop() ); + + prepare_reset(); + continue; + } + + cmd = 0; + snes_reset_prev = 0; + snes_reset_now = 0; + snes_reset_state = 0; + reset_count = 0; + + while ( fpga_test() == FPGA_TEST_TOKEN ) + { + cli_entrycheck(); + sleep_ms( 250 ); + sram_reliable(); + printf( "%s ", get_cic_statename( get_cic_state() ) ); + + if ( reset_changed ) + { + printf( "reset\n" ); + reset_changed = 0; + fpga_reset_srtc_state(); + } + + snes_reset_now = get_snes_reset(); + + if ( snes_reset_now ) + { + if ( !snes_reset_prev ) + { + printf( "RESET BUTTON DOWN\n" ); + snes_reset_state = 1; + reset_count = 0; + } + } + else + { + if ( snes_reset_prev ) + { + printf( "RESET BUTTON UP\n" ); + snes_reset_state = 0; + } + } + + if ( snes_reset_state ) + { + reset_count++; + } + else + { + sram_reliable(); + snes_main_loop(); + } + + if ( reset_count > 4 ) + { + reset_count = 0; + prepare_reset(); + break; + } + + snes_reset_prev = snes_reset_now; + } + + /* fpga test fail: panic */ + if ( fpga_test() != FPGA_TEST_TOKEN ) + { + led_panic(); + } + + /* else reset */ } - /* fpga test fail: panic */ - if(fpga_test() != FPGA_TEST_TOKEN){ - led_panic(); - } - /* else reset */ - } } diff --git a/src/memory.c b/src/memory.c index 12ee49b..c3c7cc6 100644 --- a/src/memory.c +++ b/src/memory.c @@ -45,641 +45,857 @@ #include "msu1.h" #include -char* hex = "0123456789ABCDEF"; +char *hex = "0123456789ABCDEF"; extern snes_romprops_t romprops; -void sram_hexdump(uint32_t addr, uint32_t len) { - static uint8_t buf[16]; - uint32_t ptr; - for(ptr=0; ptr < len; ptr += 16) { - sram_readblock((void*)buf, ptr+addr, 16); - uart_trace(buf, 0, 16, addr); - } -} +void sram_hexdump( uint32_t addr, uint32_t len ) +{ + static uint8_t buf[16]; + uint32_t ptr; -void sram_writebyte(uint8_t val, uint32_t addr) { - printf("WriteB %8Xh @%08lXh\n", val, addr); - set_mcu_addr(addr); - FPGA_SELECT(); - FPGA_TX_BYTE(0x98); /* WRITE */ - FPGA_TX_BYTE(val); - FPGA_WAIT_RDY(); - FPGA_DESELECT(); -} - -uint8_t sram_readbyte(uint32_t addr) { - set_mcu_addr(addr); - FPGA_SELECT(); - FPGA_TX_BYTE(0x88); /* READ */ - FPGA_WAIT_RDY(); - uint8_t val = FPGA_RX_BYTE(); - FPGA_DESELECT(); - //printf(" ReadB %8Xh @%08lXh\n", val, addr); - return val; -} - -void sram_writeshort(uint16_t val, uint32_t addr) { - printf("WriteS %8Xh @%08lXh\n", val, addr); - set_mcu_addr(addr); - FPGA_SELECT(); - FPGA_TX_BYTE(0x98); /* WRITE */ - FPGA_TX_BYTE(val&0xff); - FPGA_WAIT_RDY(); - FPGA_TX_BYTE((val>>8)&0xff); - FPGA_WAIT_RDY(); - FPGA_DESELECT(); -} - -void sram_writelong(uint32_t val, uint32_t addr) { - printf("WriteL %8lXh @%08lXh\n", val, addr); - set_mcu_addr(addr); - FPGA_SELECT(); - FPGA_TX_BYTE(0x98); /* WRITE */ - FPGA_TX_BYTE(val&0xff); - FPGA_WAIT_RDY(); - FPGA_TX_BYTE((val>>8)&0xff); - FPGA_WAIT_RDY(); - FPGA_TX_BYTE((val>>16)&0xff); - FPGA_WAIT_RDY(); - FPGA_TX_BYTE((val>>24)&0xff); - FPGA_WAIT_RDY(); - FPGA_DESELECT(); -} - -uint16_t sram_readshort(uint32_t addr) { - set_mcu_addr(addr); - FPGA_SELECT(); - FPGA_TX_BYTE(0x88); - FPGA_WAIT_RDY(); - uint32_t val = FPGA_RX_BYTE(); - FPGA_WAIT_RDY(); - val |= ((uint32_t)FPGA_RX_BYTE()<<8); - FPGA_DESELECT(); - //printf(" ReadS %8lXh @%08lXh\n", val, addr); - return val; -} - -uint32_t sram_readlong(uint32_t addr) { - set_mcu_addr(addr); - FPGA_SELECT(); - FPGA_TX_BYTE(0x88); - FPGA_WAIT_RDY(); - uint32_t val = FPGA_RX_BYTE(); - FPGA_WAIT_RDY(); - val |= ((uint32_t)FPGA_RX_BYTE()<<8); - FPGA_WAIT_RDY(); - val |= ((uint32_t)FPGA_RX_BYTE()<<16); - FPGA_WAIT_RDY(); - val |= ((uint32_t)FPGA_RX_BYTE()<<24); - FPGA_DESELECT(); - //printf(" ReadL %8lXh @%08lXh\n", val, addr); - return val; -} - -void sram_readlongblock(uint32_t* buf, uint32_t addr, uint16_t count) { - set_mcu_addr(addr); - FPGA_SELECT(); - FPGA_TX_BYTE(0x88); - uint16_t i=0; - while(i %08lX [%d]\n", addr, addr+size, size); - uint16_t count=size; - uint8_t* src = buf; - set_mcu_addr(addr); - FPGA_SELECT(); - FPGA_TX_BYTE(0x98); /* WRITE */ - while(count--) { - FPGA_TX_BYTE(*src++); - FPGA_WAIT_RDY(); - } - FPGA_DESELECT(); -} - -uint32_t load_rom(uint8_t* filename, uint32_t base_addr, uint8_t flags) { - UINT bytes_read; - DWORD filesize, read_size = 0; - UINT count=0; - tick_t ticksstart, ticks_total=0; - ticksstart=getticks(); - printf("%s\n", filename); - file_open(filename, FA_READ); - if(file_res) { - uart_putc('?'); - uart_putc(0x30+file_res); - return 0; - } - filesize = file_handle.fsize; - smc_id(&romprops); - file_close(); - /* reconfigure FPGA if necessary */ - if(romprops.fpga_conf) { - printf("reconfigure FPGA with %s...\n", romprops.fpga_conf); - fpga_pgm((uint8_t*)romprops.fpga_conf); - } - set_mcu_addr(base_addr); - file_open(filename, FA_READ); - ff_sd_offload=1; - sd_offload_tgt=0; - f_lseek(&file_handle, romprops.offset); - for(;;) { - ff_sd_offload=1; - sd_offload_tgt=0; - bytes_read = file_read(); - read_size += bytes_read; - if (file_res || !bytes_read) break; - if(!(count++ % 512)) { - uart_putc('.'); + for ( ptr = 0; ptr < len; ptr += 16 ) + { + sram_readblock( ( void * )buf, ptr + addr, 16 ); + uart_trace( buf, 0, 16, addr ); } - } - file_close(); - printf("Read %ld [%08lX] bytes...\n", read_size, read_size); - set_mapper(romprops.mapper_id); - printf("rom header map: %02x; mapper id: %d\n", romprops.header.map, romprops.mapper_id); - ticks_total=getticks()-ticksstart; - printf("%u ticks total\n", ticks_total); - if(romprops.mapper_id==3) { - printf("BSX Flash cart image\n"); - printf("attempting to load BSX BIOS /sd2snes/bsxbios.bin...\n"); - load_sram_offload((uint8_t*)"/sd2snes/bsxbios.bin", 0x800000); - printf("attempting to load BS data file /sd2snes/bsxpage.bin...\n"); - load_sram_offload((uint8_t*)"/sd2snes/bsxpage.bin", 0x900000); - printf("Type: %02x\n", romprops.header.destcode); - set_bsx_regs(0xc0, 0x3f); - uint16_t rombase; - if(romprops.header.ramsize & 1) { - rombase = 0xff00; -// set_bsx_regs(0x36, 0xc9); - } else { - rombase = 0x7f00; -// set_bsx_regs(0x34, 0xcb); - } - sram_writebyte(0x33, rombase+0xda); - sram_writebyte(0x00, rombase+0xd4); - sram_writebyte(0xfc, rombase+0xd5); - set_fpga_time(0x0220110301180530LL); - } - if(romprops.has_dspx || romprops.has_cx4) { - printf("DSPx game. Loading firmware image %s...\n", romprops.dsp_fw); - load_dspx(romprops.dsp_fw, romprops.fpga_features); - /* fallback to DSP1B firmware if DSP1.bin is not present */ - if(file_res && romprops.dsp_fw == DSPFW_1) { - load_dspx(DSPFW_1B, romprops.fpga_features); - } - if(file_res) { - snes_menu_errmsg(MENU_ERR_NODSP, (void*)romprops.dsp_fw); - } - } - uint32_t rammask; - uint32_t rommask; - - while(filesize > (romprops.romsize_bytes + romprops.offset)) { - romprops.romsize_bytes <<= 1; - } - - if(romprops.header.ramsize == 0) { - rammask = 0; - } else { - rammask = romprops.ramsize_bytes - 1; - } - rommask = romprops.romsize_bytes - 1; - if (rommask >= SRAM_SAVE_ADDR) - rommask = SRAM_SAVE_ADDR - 1; - - printf("ramsize=%x rammask=%lx\nromsize=%x rommask=%lx\n", romprops.header.ramsize, rammask, romprops.header.romsize, rommask); - set_saveram_mask(rammask); - set_rom_mask(rommask); - readled(0); - if(flags & LOADROM_WITH_SRAM) { - if(romprops.ramsize_bytes) { - strcpy(strrchr((char*)filename, (int)'.'), ".srm"); - printf("SRM file: %s\n", filename); - load_sram(filename, SRAM_SAVE_ADDR); - } else { - printf("No SRAM\n"); - } - } - - printf("check MSU..."); - if(msu1_check(filename)) { - romprops.fpga_features |= FEAT_MSU1; - romprops.has_msu1 = 1; - } else { - romprops.has_msu1 = 0; - } - printf("done\n"); - - romprops.fpga_features |= FEAT_SRTC; - romprops.fpga_features |= FEAT_213F; - - fpga_set_213f(romprops.region); - fpga_set_features(romprops.fpga_features); - - if(flags & LOADROM_WITH_RESET) { - fpga_dspx_reset(1); - snes_reset_pulse(); - fpga_dspx_reset(0); - } - - return (uint32_t)filesize; } -uint32_t load_spc(uint8_t* filename, uint32_t spc_data_addr, uint32_t spc_header_addr) { - DWORD filesize; - UINT bytes_read; - uint8_t data; - UINT j; - - printf("%s\n", filename); - - file_open(filename, FA_READ); /* Open SPC file */ - if(file_res) return 0; - filesize = file_handle.fsize; - if (filesize < 65920) { /* At this point, we care about filesize only */ - file_close(); /* since SNES decides if it is an SPC file */ - sram_writebyte(0, spc_header_addr); /* If file is too small, destroy previous SPC header */ - return 0; - } - - set_mcu_addr(spc_data_addr); - f_lseek(&file_handle, 0x100L); /* Load 64K data segment */ - - for(;;) { - bytes_read = file_read(); - if (file_res || !bytes_read) break; +void sram_writebyte( uint8_t val, uint32_t addr ) +{ + //printf("WriteB %8Xh @%08lXh\n", val, addr); + set_mcu_addr( addr ); FPGA_SELECT(); - FPGA_TX_BYTE(0x98); - for(j=0; j> 8 ) & 0xff ); + FPGA_WAIT_RDY(); FPGA_DESELECT(); - /*num = */file_write(); - if(file_res) { - uart_putc(0x30+file_res); - } - } - file_close(); } - -uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size) { - uint8_t data; - uint32_t count; - uint32_t crc; - crc=0; - crc_valid=1; - set_mcu_addr(base_addr); - FPGA_SELECT(); - FPGA_TX_BYTE(0x88); - for(count=0; count> 8 ) & 0xff ); FPGA_WAIT_RDY(); - } - FPGA_DESELECT(); -} - -uint64_t sram_gettime(uint32_t base_addr) { - set_mcu_addr(base_addr); - FPGA_SELECT(); - FPGA_TX_BYTE(0x88); - uint8_t data; - uint64_t result = 0LL; - /* 1st nibble is the century - 10 (binary) - 4th nibble is the month (binary) - all other fields are BCD */ - for(int i=0; i<12; i++) { + FPGA_TX_BYTE( ( val >> 16 ) & 0xff ); FPGA_WAIT_RDY(); - data = FPGA_RX_BYTE(); - data &= 0xf; - switch(i) { - case 0: - result = (result << 4) | ((data / 10) + 1); - result = (result << 4) | (data % 10); - break; - case 3: - result = (result << 4) | ((data / 10)); - result = (result << 4) | (data % 10); - break; - default: - result = (result << 4) | data; - } - } - FPGA_DESELECT(); - return result & 0x00ffffffffffffffLL; + FPGA_TX_BYTE( ( val >> 24 ) & 0xff ); + FPGA_WAIT_RDY(); + FPGA_DESELECT(); } -void load_dspx(const uint8_t *filename, uint8_t coretype) { - UINT bytes_read; - //DWORD filesize; - uint16_t word_cnt; - uint8_t wordsize_cnt = 0; - uint16_t sector_remaining = 0; - uint16_t sector_cnt = 0; - uint16_t pgmsize = 0; - uint16_t datsize = 0; - uint32_t pgmdata = 0; - uint16_t datdata = 0; +uint16_t sram_readshort( uint32_t addr ) +{ + set_mcu_addr( addr ); + FPGA_SELECT(); + FPGA_TX_BYTE( 0x88 ); + FPGA_WAIT_RDY(); + uint32_t val = FPGA_RX_BYTE(); + FPGA_WAIT_RDY(); + val |= ( ( uint32_t )FPGA_RX_BYTE() << 8 ); + FPGA_DESELECT(); + //printf(" ReadS %8lXh @%08lXh\n", val, addr); + return val; +} - if(coretype & FEAT_ST0010) { - datsize = 1536; - pgmsize = 2048; - } else if (coretype & FEAT_DSPX) { - datsize = 1024; - pgmsize = 2048; - } else if (coretype & FEAT_CX4) { - datsize = 0; - pgmsize = 1024; /* Cx4 data ROM */ - } else { - printf("load_dspx: unknown core (%02x)!\n", coretype); - } +uint32_t sram_readlong( uint32_t addr ) +{ + set_mcu_addr( addr ); + FPGA_SELECT(); + FPGA_TX_BYTE( 0x88 ); + FPGA_WAIT_RDY(); + uint32_t val = FPGA_RX_BYTE(); + FPGA_WAIT_RDY(); + val |= ( ( uint32_t )FPGA_RX_BYTE() << 8 ); + FPGA_WAIT_RDY(); + val |= ( ( uint32_t )FPGA_RX_BYTE() << 16 ); + FPGA_WAIT_RDY(); + val |= ( ( uint32_t )FPGA_RX_BYTE() << 24 ); + FPGA_DESELECT(); + //printf(" ReadL %8lXh @%08lXh\n", val, addr); + return val; +} - file_open((uint8_t*)filename, FA_READ); - /*filesize = file_handle.fsize;*/ - if(file_res) { - printf("Could not read %s: error %d\n", filename, file_res); - return; - } +void sram_readlongblock( uint32_t *buf, uint32_t addr, uint16_t count ) +{ + set_mcu_addr( addr ); + FPGA_SELECT(); + FPGA_TX_BYTE( 0x88 ); + uint16_t i = 0; - fpga_reset_dspx_addr(); - - for(word_cnt = 0; word_cnt < pgmsize;) { - if(!sector_remaining) { - bytes_read = file_read(); - sector_remaining = bytes_read; - sector_cnt = 0; + while ( i < count ) + { + FPGA_WAIT_RDY(); + uint32_t val = ( uint32_t )FPGA_RX_BYTE() << 24; + FPGA_WAIT_RDY(); + val |= ( ( uint32_t )FPGA_RX_BYTE() << 16 ); + FPGA_WAIT_RDY(); + val |= ( ( uint32_t )FPGA_RX_BYTE() << 8 ); + FPGA_WAIT_RDY(); + val |= FPGA_RX_BYTE(); + buf[i++] = val; } - pgmdata = (pgmdata << 8) | file_buf[sector_cnt]; - sector_cnt++; - wordsize_cnt++; - sector_remaining--; - if(wordsize_cnt == 3){ - wordsize_cnt = 0; - word_cnt++; - fpga_write_dspx_pgm(pgmdata); + + FPGA_DESELECT(); +} + +void sram_readblock( void *buf, uint32_t addr, uint16_t size ) +{ + uint16_t count = size; + uint8_t *tgt = buf; + set_mcu_addr( addr ); + FPGA_SELECT(); + FPGA_TX_BYTE( 0x88 ); /* READ */ + + while ( count-- ) + { + FPGA_WAIT_RDY(); + *( tgt++ ) = FPGA_RX_BYTE(); } - } - wordsize_cnt = 0; - if(coretype & FEAT_ST0010) { - file_seek(0xc000); - sector_remaining = 0; - } + FPGA_DESELECT(); +} - for(word_cnt = 0; word_cnt < datsize;) { - if(!sector_remaining) { - bytes_read = file_read(); - sector_remaining = bytes_read; - sector_cnt = 0; +void sram_readstrn( void *buf, uint32_t addr, uint16_t size ) +{ + uint16_t count = size; + uint8_t *tgt = buf; + set_mcu_addr( addr ); + FPGA_SELECT(); + FPGA_TX_BYTE( 0x88 ); /* READ */ + + while ( count-- ) + { + FPGA_WAIT_RDY(); + + if ( !( *( tgt++ ) = FPGA_RX_BYTE() ) ) + { + break; + } } - datdata = (datdata << 8) | file_buf[sector_cnt]; - sector_cnt++; - wordsize_cnt++; - sector_remaining--; - if(wordsize_cnt == 2){ - wordsize_cnt = 0; - word_cnt++; - fpga_write_dspx_dat(datdata); + + FPGA_DESELECT(); +} + +void sram_writeblock( void *buf, uint32_t addr, uint16_t size ) +{ + //printf("WriteZ %08lX -> %08lX [%d]\n", addr, addr+size, size); + uint16_t count = size; + uint8_t *src = buf; + set_mcu_addr( addr ); + FPGA_SELECT(); + FPGA_TX_BYTE( 0x98 ); /* WRITE */ + + while ( count-- ) + { + FPGA_TX_BYTE( *src++ ); + FPGA_WAIT_RDY(); } - } - fpga_reset_dspx_addr(); + FPGA_DESELECT(); +} - file_close(); +uint32_t load_rom( uint8_t *filename, uint32_t base_addr, uint8_t flags ) +{ + UINT bytes_read; + DWORD filesize, read_size = 0; + UINT count = 0; + tick_t ticksstart, ticks_total = 0; + ticksstart = getticks(); + printf( "%s\n", filename ); + file_open( filename, FA_READ ); + + if ( file_res ) + { + uart_putc( '?' ); + uart_putc( 0x30 + file_res ); + return 0; + } + + filesize = file_handle.fsize; + smc_id( &romprops ); + file_close(); + + /* reconfigure FPGA if necessary */ + if ( romprops.fpga_conf ) + { + printf( "reconfigure FPGA with %s...\n", romprops.fpga_conf ); + fpga_pgm( ( uint8_t * )romprops.fpga_conf ); + } + + set_mcu_addr( base_addr ); + file_open( filename, FA_READ ); + ff_sd_offload = 1; + sd_offload_tgt = 0; + f_lseek( &file_handle, romprops.offset ); + + for ( ;; ) + { + ff_sd_offload = 1; + sd_offload_tgt = 0; + bytes_read = file_read(); + read_size += bytes_read; + + if ( file_res || !bytes_read ) + { + break; + } + + if ( !( count++ % 512 ) ) + { + uart_putc( '.' ); + } + } + + file_close(); + printf( "Read %ld [%08lX] bytes...\n", read_size, read_size ); + set_mapper( romprops.mapper_id ); + printf( "rom header map: %02x; mapper id: %d\n", romprops.header.map, romprops.mapper_id ); + ticks_total = getticks() - ticksstart; + printf( "%u ticks total\n", ticks_total ); + + if ( romprops.mapper_id == 3 ) + { + printf( "BSX Flash cart image\n" ); + printf( "attempting to load BSX BIOS /sd2snes/bsxbios.bin...\n" ); + load_sram_offload( ( uint8_t * )"/sd2snes/bsxbios.bin", 0x800000 ); + printf( "attempting to load BS data file /sd2snes/bsxpage.bin...\n" ); + load_sram_offload( ( uint8_t * )"/sd2snes/bsxpage.bin", 0x900000 ); + printf( "Type: %02x\n", romprops.header.destcode ); + set_bsx_regs( 0xc0, 0x3f ); + uint16_t rombase; + + if ( romprops.header.ramsize & 1 ) + { + rombase = 0xff00; + // set_bsx_regs(0x36, 0xc9); + } + else + { + rombase = 0x7f00; + // set_bsx_regs(0x34, 0xcb); + } + + sram_writebyte( 0x33, rombase + 0xda ); + sram_writebyte( 0x00, rombase + 0xd4 ); + sram_writebyte( 0xfc, rombase + 0xd5 ); + set_fpga_time( 0x0220110301180530LL ); + } + + if ( romprops.has_dspx || romprops.has_cx4 ) + { + printf( "DSPx game. Loading firmware image %s...\n", romprops.dsp_fw ); + load_dspx( romprops.dsp_fw, romprops.fpga_features ); + + /* fallback to DSP1B firmware if DSP1.bin is not present */ + if ( file_res && romprops.dsp_fw == DSPFW_1 ) + { + load_dspx( DSPFW_1B, romprops.fpga_features ); + } + + if ( file_res ) + { + snes_menu_errmsg( MENU_ERR_NODSP, ( void * )romprops.dsp_fw ); + } + } + + uint32_t rammask; + uint32_t rommask; + + while ( filesize > ( romprops.romsize_bytes + romprops.offset ) ) + { + romprops.romsize_bytes <<= 1; + } + + if ( romprops.header.ramsize == 0 ) + { + rammask = 0; + } + else + { + rammask = romprops.ramsize_bytes - 1; + } + + rommask = romprops.romsize_bytes - 1; + + if ( rommask >= SRAM_SAVE_ADDR ) + { + rommask = SRAM_SAVE_ADDR - 1; + } + + printf( "ramsize=%x rammask=%lx\nromsize=%x rommask=%lx\n", romprops.header.ramsize, rammask, romprops.header.romsize, + rommask ); + set_saveram_mask( rammask ); + set_rom_mask( rommask ); + readled( 0 ); + + if ( flags & LOADROM_WITH_SRAM ) + { + if ( romprops.ramsize_bytes ) + { + strcpy( strrchr( ( char * )filename, ( int )'.' ), ".srm" ); + printf( "SRM file: %s\n", filename ); + load_sram( filename, SRAM_SAVE_ADDR ); + } + else + { + printf( "No SRAM\n" ); + } + } + + printf( "check MSU..." ); + + if ( msu1_check( filename ) ) + { + romprops.fpga_features |= FEAT_MSU1; + romprops.has_msu1 = 1; + } + else + { + romprops.has_msu1 = 0; + } + + printf( "done\n" ); + + romprops.fpga_features |= FEAT_SRTC; + romprops.fpga_features |= FEAT_213F; + + fpga_set_213f( romprops.region ); + fpga_set_features( romprops.fpga_features ); + + if ( flags & LOADROM_WITH_RESET ) + { + fpga_dspx_reset( 1 ); + snes_reset_pulse(); + fpga_dspx_reset( 0 ); + } + + return ( uint32_t )filesize; +} + +uint32_t load_spc( uint8_t *filename, uint32_t spc_data_addr, uint32_t spc_header_addr ) +{ + DWORD filesize; + UINT bytes_read; + uint8_t data; + UINT j; + + printf( "%s\n", filename ); + + file_open( filename, FA_READ ); /* Open SPC file */ + + if ( file_res ) + { + return 0; + } + + filesize = file_handle.fsize; + + if ( filesize < 65920 ) /* At this point, we care about filesize only */ + { + file_close(); /* since SNES decides if it is an SPC file */ + sram_writebyte( 0, spc_header_addr ); /* If file is too small, destroy previous SPC header */ + return 0; + } + + set_mcu_addr( spc_data_addr ); + f_lseek( &file_handle, 0x100L ); /* Load 64K data segment */ + + for ( ;; ) + { + bytes_read = file_read(); + + if ( file_res || !bytes_read ) + { + break; + } + + FPGA_SELECT(); + FPGA_TX_BYTE( 0x98 ); + + for ( j = 0; j < bytes_read; j++ ) + { + FPGA_TX_BYTE( file_buf[j] ); + FPGA_WAIT_RDY(); + } + + FPGA_DESELECT(); + } + + file_close(); + file_open( filename, FA_READ ); /* Reopen SPC file to reset file_getc state*/ + + set_mcu_addr( spc_header_addr ); + f_lseek( &file_handle, 0x0L ); /* Load 256 bytes header */ + + FPGA_SELECT(); + FPGA_TX_BYTE( 0x98 ); + + for ( j = 0; j < 256; j++ ) + { + data = file_getc(); + FPGA_TX_BYTE( data ); + FPGA_WAIT_RDY(); + } + + FPGA_DESELECT(); + + file_close(); + file_open( filename, FA_READ ); /* Reopen SPC file to reset file_getc state*/ + + set_mcu_addr( spc_header_addr + 0x100 ); + f_lseek( &file_handle, 0x10100L ); /* Load 128 DSP registers */ + + FPGA_SELECT(); + FPGA_TX_BYTE( 0x98 ); + + for ( j = 0; j < 128; j++ ) + { + data = file_getc(); + FPGA_TX_BYTE( data ); + FPGA_WAIT_RDY(); + } + + FPGA_DESELECT(); + file_close(); /* Done ! */ + + /* clear echo buffer to avoid artifacts */ + uint8_t esa = sram_readbyte( spc_header_addr + 0x100 + 0x6d ); + uint8_t edl = sram_readbyte( spc_header_addr + 0x100 + 0x7d ); + uint8_t flg = sram_readbyte( spc_header_addr + 0x100 + 0x6c ); + + if ( !( flg & 0x20 ) && ( edl & 0x0f ) ) + { + int echo_start = esa << 8; + int echo_length = ( edl & 0x0f ) << 11; + printf( "clearing echo buffer %04x-%04x...\n", echo_start, echo_start + echo_length - 1 ); + sram_memset( spc_data_addr + echo_start, echo_length, 0 ); + } + + return ( uint32_t )filesize; +} + +uint32_t load_sram_offload( uint8_t *filename, uint32_t base_addr ) +{ + set_mcu_addr( base_addr ); + UINT bytes_read; + DWORD filesize; + file_open( filename, FA_READ ); + filesize = file_handle.fsize; + + if ( file_res ) + { + return 0; + } + + for ( ;; ) + { + ff_sd_offload = 1; + sd_offload_tgt = 0; + bytes_read = file_read(); + + if ( file_res || !bytes_read ) + { + break; + } + } + + file_close(); + return ( uint32_t )filesize; +} + +uint32_t load_sram( uint8_t *filename, uint32_t base_addr ) +{ + set_mcu_addr( base_addr ); + UINT bytes_read; + DWORD filesize; + file_open( filename, FA_READ ); + filesize = file_handle.fsize; + + if ( file_res ) + { + printf( "load_sram: could not open %s, res=%d\n", filename, file_res ); + return 0; + } + + for ( ;; ) + { + bytes_read = file_read(); + + if ( file_res || !bytes_read ) + { + break; + } + + FPGA_SELECT(); + FPGA_TX_BYTE( 0x98 ); + + for ( int j = 0; j < bytes_read; j++ ) + { + FPGA_TX_BYTE( file_buf[j] ); + FPGA_WAIT_RDY(); + } + + FPGA_DESELECT(); + } + + file_close(); + return ( uint32_t )filesize; +} + +uint32_t load_sram_rle( uint8_t *filename, uint32_t base_addr ) +{ + uint8_t data; + set_mcu_addr( base_addr ); + DWORD filesize; + file_open( filename, FA_READ ); + filesize = file_handle.fsize; + + if ( file_res ) + { + return 0; + } + + FPGA_SELECT(); + FPGA_TX_BYTE( 0x98 ); + + for ( ;; ) + { + data = rle_file_getc(); + + if ( file_res || file_status ) + { + break; + } + + FPGA_TX_BYTE( data ); + FPGA_WAIT_RDY(); + } + + FPGA_DESELECT(); + file_close(); + return ( uint32_t )filesize; +} + +uint32_t load_bootrle( uint32_t base_addr ) +{ + uint8_t data; + set_mcu_addr( base_addr ); + DWORD filesize = 0; + rle_mem_init( bootrle, sizeof( bootrle ) ); + + FPGA_SELECT(); + FPGA_TX_BYTE( 0x98 ); + + for ( ;; ) + { + data = rle_mem_getc(); + + if ( rle_state ) + { + break; + } + + FPGA_TX_BYTE( data ); + FPGA_WAIT_RDY(); + filesize++; + } + + FPGA_DESELECT(); + return ( uint32_t )filesize; +} + + +void save_sram( uint8_t *filename, uint32_t sram_size, uint32_t base_addr ) +{ + uint32_t count = 0; + //uint32_t num = 0; + + FPGA_DESELECT(); + file_open( filename, FA_CREATE_ALWAYS | FA_WRITE ); + + if ( file_res ) + { + uart_putc( 0x30 + file_res ); + } + + while ( count < sram_size ) + { + set_mcu_addr( base_addr + count ); + FPGA_SELECT(); + FPGA_TX_BYTE( 0x88 ); /* read */ + + for ( int j = 0; j < sizeof( file_buf ); j++ ) + { + FPGA_WAIT_RDY(); + file_buf[j] = FPGA_RX_BYTE(); + count++; + } + + FPGA_DESELECT(); + /*num = */file_write(); + + if ( file_res ) + { + uart_putc( 0x30 + file_res ); + } + } + + file_close(); +} + + +uint32_t calc_sram_crc( uint32_t base_addr, uint32_t size ) +{ + uint8_t data; + uint32_t count; + uint32_t crc; + crc = 0; + crc_valid = 1; + set_mcu_addr( base_addr ); + FPGA_SELECT(); + FPGA_TX_BYTE( 0x88 ); + + for ( count = 0; count < size; count++ ) + { + FPGA_WAIT_RDY(); + data = FPGA_RX_BYTE(); + + if ( get_snes_reset() ) + { + crc_valid = 0; + break; + } + + crc += crc32_update( crc, data ); + } + + FPGA_DESELECT(); + return crc; +} + +uint8_t sram_reliable() +{ + uint16_t score = 0; + uint32_t val; + uint8_t result = 0; + + /*while(score= msu_page1_start + msu_page_size ) ) + && ( ( msu_offset < msu_page2_start ) + || ( msu_offset >= msu_page2_start + msu_page_size ) ) ) + { + DBG_MSU1 printf( "offset %08lx out of range (%08lx-%08lx, %08lx-%08lx), reload\n", msu_offset, msu_page1_start, + msu_page1_start + msu_page_size - 1, msu_page2_start, msu_page2_start + msu_page_size - 1 ); + /* "cache miss" */ + /* fill buffer */ + set_msu_addr( 0x0 ); + sd_offload_tgt = 2; + ff_sd_offload = 1; + msu_res = f_lseek( &msufile, msu_offset ); + DBG_MSU1 printf( "seek to %08lx, res = %d\n", msu_offset, msu_res ); + sd_offload_tgt = 2; + ff_sd_offload = 1; + msu_res = f_read( &msufile, file_buf, 16384, &msu_data_bytes_read ); + DBG_MSU1 printf( "read res = %d\n", msu_res ); + DBG_MSU1 printf( "read %d bytes\n", msu_data_bytes_read ); + msu_reset( 0x0 ); + msu_page1_start = msu_offset; + msu_page2_start = msu_offset + msu_page_size; + } + else + { + if ( msu_offset >= msu_page1_start && msu_offset <= msu_page1_start + msu_page_size ) + { + msu_reset( 0x0000 + msu_offset - msu_page1_start ); + DBG_MSU1 printf( "inside page1, new offset: %08lx\n", 0x0000 + msu_offset - msu_page1_start ); + + if ( !( msu_page2_start == msu_page1_start + msu_page_size ) ) + { + set_msu_addr( 0x2000 ); + sd_offload_tgt = 2; + ff_sd_offload = 1; + f_read( &msufile, file_buf, 8192, &msu_data_bytes_read ); + DBG_MSU1 printf( "next page dirty (was: %08lx), loaded page2 (start now: ", msu_page2_start ); + msu_page2_start = msu_page1_start + msu_page_size; + DBG_MSU1 printf( "%08lx)\n", msu_page2_start ); + } + } + else if ( msu_offset >= msu_page2_start && msu_offset <= msu_page2_start + msu_page_size ) + { + DBG_MSU1 printf( "inside page2, new offset: %08lx\n", 0x2000 + msu_offset - msu_page2_start ); + msu_reset( 0x2000 + msu_offset - msu_page2_start ); + + if ( !( msu_page1_start == msu_page2_start + msu_page_size ) ) + { + set_msu_addr( 0x0 ); + sd_offload_tgt = 2; + ff_sd_offload = 1; + f_read( &msufile, file_buf, 8192, &msu_data_bytes_read ); + DBG_MSU1 printf( "next page dirty (was: %08lx), loaded page1 (start now: ", msu_page1_start ); + msu_page1_start = msu_page2_start + msu_page_size; + DBG_MSU1 printf( "%08lx)\n", msu_page1_start ); + } + } + else + { + printf( "!!!WATWATWAT!!!\n" ); + } + } + + /* clear bank bit to mask bank reset artifact */ + fpga_status_now &= ~0x2000; + fpga_status_prev &= ~0x2000; + /* clear busy bit */ + set_msu_status( 0x00, 0x10 ); +} + +int msu1_check_reset( void ) +{ + static tick_t rising_ticks; + + static uint8_t resbutton = 0, resbutton_prev = 0; + int result = MSU_RESET_NONE; + resbutton = get_snes_reset(); + + if ( resbutton && !resbutton_prev ) /* push */ + { + rising_ticks = getticks(); + } + else if ( resbutton && resbutton_prev ) /* hold */ + { + if ( getticks() > rising_ticks + 99 ) + { + result = MSU_RESET_LONG; + } + } + else if ( !resbutton && resbutton_prev ) /* release */ + { + if ( getticks() < rising_ticks + 99 ) + { + result = MSU_RESET_SHORT; + } + } + else + { + result = MSU_RESET_NONE; + } + + resbutton_prev = resbutton; + return result; +} + +int msu1_check( uint8_t *filename ) +{ + /* open MSU file */ + strcpy( ( char * )file_buf, ( char * )filename ); + strcpy( strrchr( ( char * )file_buf, ( int )'.' ), ".msu" ); + printf( "MSU datafile: %s\n", file_buf ); + + if ( f_open( &msufile, ( const TCHAR * )file_buf, FA_READ ) != FR_OK ) + { + printf( "MSU datafile not found\n" ); + return 0; + } + + msufile.cltbl = msu_cltbl; + msu_cltbl[0] = CLTBL_SIZE; + + if ( f_lseek( &msufile, CREATE_LINKMAP ) ) + { + printf( "Error creating FF linkmap for MSU file!\n" ); + } + + romprops.fpga_features |= FEAT_MSU1; + return 1; +} + +int msu1_loop() +{ + /* it is assumed that the MSU file is already opened by calling msu1_check(). */ + while ( fpga_status() & 0x4000 ); + + uint16_t dac_addr = 0; + uint16_t msu_addr = 0; + uint8_t msu_repeat = 0; + uint16_t msu_track = 0; + uint32_t msu_offset = 0; + fpga_status_prev = fpga_status(); + fpga_status_now = fpga_status(); + int msu_res; + + /* set_msu_addr(0x0); + msu_reset(0x0); + ff_sd_offload=1; + sd_offload_tgt=2; + f_lseek(&msufile, 0L); + ff_sd_offload=1; + sd_offload_tgt=2; + f_read(&msufile, file_buf, 16384, &msu_data_bytes_read); + */ + set_dac_addr( dac_addr ); dac_pause(); dac_reset(); - ff_sd_offload=1; - sd_offload_tgt=1; - f_read(&file_handle, file_buf, MSU_DAC_BUFSIZE, &msu_audio_bytes_read); - /* clear busy bit */ - set_msu_status(0x00, 0x28); /* set no bits, reset audio_busy + audio_error */ - } else { - f_close(&file_handle); - set_msu_status(0x08, 0x20); /* reset audio_busy, set audio_error */ - } -} -void prepare_data(uint32_t msu_offset) { - DBG_MSU1 printf("Data requested! Offset=%08lx page1=%08lx page2=%08lx\n", msu_offset, msu_page1_start, msu_page2_start); - if( ((msu_offset < msu_page1_start) - || (msu_offset >= msu_page1_start + msu_page_size)) - && ((msu_offset < msu_page2_start) - || (msu_offset >= msu_page2_start + msu_page_size))) { - DBG_MSU1 printf("offset %08lx out of range (%08lx-%08lx, %08lx-%08lx), reload\n", msu_offset, msu_page1_start, - msu_page1_start+msu_page_size-1, msu_page2_start, msu_page2_start+msu_page_size-1); - /* "cache miss" */ - /* fill buffer */ - set_msu_addr(0x0); - sd_offload_tgt=2; - ff_sd_offload=1; - msu_res = f_lseek(&msufile, msu_offset); - DBG_MSU1 printf("seek to %08lx, res = %d\n", msu_offset, msu_res); - sd_offload_tgt=2; - ff_sd_offload=1; - msu_res = f_read(&msufile, file_buf, 16384, &msu_data_bytes_read); - DBG_MSU1 printf("read res = %d\n", msu_res); - DBG_MSU1 printf("read %d bytes\n", msu_data_bytes_read); - msu_reset(0x0); - msu_page1_start = msu_offset; - msu_page2_start = msu_offset + msu_page_size; - } else { - if (msu_offset >= msu_page1_start && msu_offset <= msu_page1_start + msu_page_size) { - msu_reset(0x0000 + msu_offset - msu_page1_start); - DBG_MSU1 printf("inside page1, new offset: %08lx\n", 0x0000 + msu_offset-msu_page1_start); - if(!(msu_page2_start == msu_page1_start + msu_page_size)) { - set_msu_addr(0x2000); - sd_offload_tgt=2; - ff_sd_offload=1; - f_read(&msufile, file_buf, 8192, &msu_data_bytes_read); - DBG_MSU1 printf("next page dirty (was: %08lx), loaded page2 (start now: ", msu_page2_start); - msu_page2_start = msu_page1_start + msu_page_size; - DBG_MSU1 printf("%08lx)\n", msu_page2_start); - } - } else if (msu_offset >= msu_page2_start && msu_offset <= msu_page2_start + msu_page_size) { - DBG_MSU1 printf("inside page2, new offset: %08lx\n", 0x2000 + msu_offset-msu_page2_start); - msu_reset(0x2000 + msu_offset - msu_page2_start); - if(!(msu_page1_start == msu_page2_start + msu_page_size)) { - set_msu_addr(0x0); - sd_offload_tgt=2; - ff_sd_offload=1; - f_read(&msufile, file_buf, 8192, &msu_data_bytes_read); - DBG_MSU1 printf("next page dirty (was: %08lx), loaded page1 (start now: ", msu_page1_start); - msu_page1_start = msu_page2_start + msu_page_size; - DBG_MSU1 printf("%08lx)\n", msu_page1_start); - } - } else printf("!!!WATWATWAT!!!\n"); - } - /* clear bank bit to mask bank reset artifact */ - fpga_status_now &= ~0x2000; - fpga_status_prev &= ~0x2000; - /* clear busy bit */ - set_msu_status(0x00, 0x10); -} + set_msu_addr( 0x0 ); + msu_reset( 0x0 ); + ff_sd_offload = 1; + sd_offload_tgt = 2; + f_lseek( &msufile, 0L ); + ff_sd_offload = 1; + sd_offload_tgt = 2; + f_read( &msufile, file_buf, 16384, &msu_data_bytes_read ); -int msu1_check_reset(void) { - static tick_t rising_ticks; + prepare_audio_track( 0 ); + prepare_data( 0 ); - static uint8_t resbutton=0, resbutton_prev=0; - int result = MSU_RESET_NONE; - resbutton = get_snes_reset(); - if(resbutton && !resbutton_prev) { /* push */ - rising_ticks = getticks(); - } else if(resbutton && resbutton_prev) { /* hold */ - if(getticks() > rising_ticks + 99) { - result = MSU_RESET_LONG; + /* audio_start, data_start, 0, audio_ctrl[1:0], ctrl_start */ + while ( ( msu_res = msu1_check_reset() ) == MSU_RESET_NONE ) + { + cli_entrycheck(); + fpga_status_now = fpga_status(); + + /* Data buffer refill */ + if ( ( fpga_status_now & 0x2000 ) != ( fpga_status_prev & 0x2000 ) ) + { + DBG_MSU1 printf( "data\n" ); + + if ( fpga_status_now & 0x2000 ) + { + msu_addr = 0x0; + msu_page1_start = msu_page2_start + msu_page_size; + } + else + { + msu_addr = 0x2000; + msu_page2_start = msu_page1_start + msu_page_size; + } + + set_msu_addr( msu_addr ); + sd_offload_tgt = 2; + ff_sd_offload = 1; + msu_res = f_read( &msufile, file_buf, 8192, &msu_data_bytes_read ); + DBG_MSU1 printf( "data buffer refilled. res=%d page1=%08lx page2=%08lx\n", msu_res, msu_page1_start, msu_page2_start ); + } + + /* Audio buffer refill */ + if ( ( fpga_status_now & 0x4000 ) != ( fpga_status_prev & 0x4000 ) ) + { + if ( fpga_status_now & 0x4000 ) + { + dac_addr = 0; + } + else + { + dac_addr = MSU_DAC_BUFSIZE / 2; + } + + set_dac_addr( dac_addr ); + sd_offload_tgt = 1; + ff_sd_offload = 1; + f_read( &file_handle, file_buf, MSU_DAC_BUFSIZE / 2, &msu_audio_bytes_read ); + } + + if ( fpga_status_now & 0x0020 ) + { + /* get trackno */ + msu_track = get_msu_track(); + DBG_MSU1 printf( "Audio requested! Track=%d\n", msu_track ); + + prepare_audio_track( msu_track ); + } + + if ( fpga_status_now & 0x0010 ) + { + /* get address */ + msu_offset = get_msu_offset(); + prepare_data( msu_offset ); + } + + if ( fpga_status_now & 0x0001 ) + { + if ( fpga_status_now & 0x0004 ) + { + msu_repeat = 1; + set_msu_status( 0x04, 0x01 ); /* set bit 2, reset bit 0 */ + DBG_MSU1 printf( "Repeat set!\n" ); + } + else + { + msu_repeat = 0; + set_msu_status( 0x00, 0x05 ); /* set no bits, reset bit 0+2 */ + DBG_MSU1 printf( "Repeat clear!\n" ); + } + + if ( fpga_status_now & 0x0002 ) + { + DBG_MSU1 printf( "PLAY!\n" ); + set_msu_status( 0x02, 0x01 ); /* set bit 0, reset bit 1 */ + dac_play(); + } + else + { + DBG_MSU1 printf( "PAUSE!\n" ); + set_msu_status( 0x00, 0x03 ); /* set no bits, reset bit 1+0 */ + dac_pause(); + } + } + + fpga_status_prev = fpga_status_now; + + /* handle loop / end */ + if ( msu_audio_bytes_read < MSU_DAC_BUFSIZE / 2 ) + { + ff_sd_offload = 0; + sd_offload = 0; + + if ( msu_repeat ) + { + DBG_MSU1 printf( "loop\n" ); + ff_sd_offload = 1; + sd_offload_tgt = 1; + f_lseek( &file_handle, 8L + msu_loop_point * 4 ); + ff_sd_offload = 1; + sd_offload_tgt = 1; + f_read( &file_handle, file_buf, ( MSU_DAC_BUFSIZE / 2 ) - msu_audio_bytes_read, &msu_audio_bytes_read ); + } + else + { + set_msu_status( 0x00, 0x02 ); /* clear play bit */ + dac_pause(); + } + + msu_audio_bytes_read = MSU_DAC_BUFSIZE; + } } - } else if(!resbutton && resbutton_prev) { /* release */ - if(getticks() < rising_ticks + 99) { - result = MSU_RESET_SHORT; - } - } else { - result = MSU_RESET_NONE; - } - resbutton_prev = resbutton; - return result; -} -int msu1_check(uint8_t* filename) { -/* open MSU file */ - strcpy((char*)file_buf, (char*)filename); - strcpy(strrchr((char*)file_buf, (int)'.'), ".msu"); - printf("MSU datafile: %s\n", file_buf); - if(f_open(&msufile, (const TCHAR*)file_buf, FA_READ) != FR_OK) { - printf("MSU datafile not found\n"); + f_close( &file_handle ); + DBG_MSU1 printf( "Reset " ); + + if ( msu_res == MSU_RESET_LONG ) + { + f_close( &msufile ); + DBG_MSU1 printf( "to menu\n" ); + return 1; + } + + DBG_MSU1 printf( "game\n" ); return 0; - } - msufile.cltbl = msu_cltbl; - msu_cltbl[0] = CLTBL_SIZE; - if(f_lseek(&msufile, CREATE_LINKMAP)) { - printf("Error creating FF linkmap for MSU file!\n"); - } - romprops.fpga_features |= FEAT_MSU1; - return 1; -} - -int msu1_loop() { -/* it is assumed that the MSU file is already opened by calling msu1_check(). */ - while(fpga_status() & 0x4000); - uint16_t dac_addr = 0; - uint16_t msu_addr = 0; - uint8_t msu_repeat = 0; - uint16_t msu_track = 0; - uint32_t msu_offset = 0; - fpga_status_prev = fpga_status(); - fpga_status_now = fpga_status(); - int msu_res; - -/* set_msu_addr(0x0); - msu_reset(0x0); - ff_sd_offload=1; - sd_offload_tgt=2; - f_lseek(&msufile, 0L); - ff_sd_offload=1; - sd_offload_tgt=2; - f_read(&msufile, file_buf, 16384, &msu_data_bytes_read); -*/ - set_dac_addr(dac_addr); - dac_pause(); - dac_reset(); - - set_msu_addr(0x0); - msu_reset(0x0); - ff_sd_offload=1; - sd_offload_tgt=2; - f_lseek(&msufile, 0L); - ff_sd_offload=1; - sd_offload_tgt=2; - f_read(&msufile, file_buf, 16384, &msu_data_bytes_read); - - prepare_audio_track(0); - prepare_data(0); -/* audio_start, data_start, 0, audio_ctrl[1:0], ctrl_start */ - while((msu_res = msu1_check_reset()) == MSU_RESET_NONE){ - cli_entrycheck(); - fpga_status_now = fpga_status(); - - /* Data buffer refill */ - if((fpga_status_now & 0x2000) != (fpga_status_prev & 0x2000)) { - DBG_MSU1 printf("data\n"); - if(fpga_status_now & 0x2000) { - msu_addr = 0x0; - msu_page1_start = msu_page2_start + msu_page_size; - } else { - msu_addr = 0x2000; - msu_page2_start = msu_page1_start + msu_page_size; - } - set_msu_addr(msu_addr); - sd_offload_tgt=2; - ff_sd_offload=1; - msu_res = f_read(&msufile, file_buf, 8192, &msu_data_bytes_read); - DBG_MSU1 printf("data buffer refilled. page=%d res=%d page1=%08lx page2=%08lx\n", pageno, msu_res, msu_page1_start, msu_page2_start); - } - - /* Audio buffer refill */ - if((fpga_status_now & 0x4000) != (fpga_status_prev & 0x4000)) { - if(fpga_status_now & 0x4000) { - dac_addr = 0; - } else { - dac_addr = MSU_DAC_BUFSIZE/2; - } - set_dac_addr(dac_addr); - sd_offload_tgt=1; - ff_sd_offload=1; - f_read(&file_handle, file_buf, MSU_DAC_BUFSIZE/2, &msu_audio_bytes_read); - } - - if(fpga_status_now & 0x0020) { - /* get trackno */ - msu_track = get_msu_track(); - DBG_MSU1 printf("Audio requested! Track=%d\n", msu_track); - - prepare_audio_track(msu_track); - } - - if(fpga_status_now & 0x0010) { - /* get address */ - msu_offset=get_msu_offset(); - prepare_data(msu_offset); - } - - if(fpga_status_now & 0x0001) { - if(fpga_status_now & 0x0004) { - msu_repeat = 1; - set_msu_status(0x04, 0x01); /* set bit 2, reset bit 0 */ - DBG_MSU1 printf("Repeat set!\n"); - } else { - msu_repeat = 0; - set_msu_status(0x00, 0x05); /* set no bits, reset bit 0+2 */ - DBG_MSU1 printf("Repeat clear!\n"); - } - - if(fpga_status_now & 0x0002) { - DBG_MSU1 printf("PLAY!\n"); - set_msu_status(0x02, 0x01); /* set bit 0, reset bit 1 */ - dac_play(); - } else { - DBG_MSU1 printf("PAUSE!\n"); - set_msu_status(0x00, 0x03); /* set no bits, reset bit 1+0 */ - dac_pause(); - } - } - - fpga_status_prev = fpga_status_now; - - /* handle loop / end */ - if(msu_audio_bytes_read < MSU_DAC_BUFSIZE / 2) { - ff_sd_offload=0; - sd_offload=0; - if(msu_repeat) { - DBG_MSU1 printf("loop\n"); - ff_sd_offload=1; - sd_offload_tgt=1; - f_lseek(&file_handle, 8L+msu_loop_point*4); - ff_sd_offload=1; - sd_offload_tgt=1; - f_read(&file_handle, file_buf, (MSU_DAC_BUFSIZE / 2) - msu_audio_bytes_read, &msu_audio_bytes_read); - } else { - set_msu_status(0x00, 0x02); /* clear play bit */ - dac_pause(); - } - msu_audio_bytes_read = MSU_DAC_BUFSIZE; - } - } - f_close(&file_handle); - DBG_MSU1 printf("Reset "); - if(msu_res == MSU_RESET_LONG) { - f_close(&msufile); - DBG_MSU1 printf("to menu\n"); - return 1; - } - DBG_MSU1 printf("game\n"); - return 0; } /* END OF MSU1 STUFF */ diff --git a/src/msu1.h b/src/msu1.h index 1407a32..ae4c129 100644 --- a/src/msu1.h +++ b/src/msu1.h @@ -7,9 +7,9 @@ #define DBG_MSU1 while(0) #endif -#define MSU_DAC_BUFSIZE (2048) +#define MSU_DAC_BUFSIZE (2048) -int msu1_check(uint8_t*); -int msu1_loop(void); +int msu1_check( uint8_t * ); +int msu1_loop( void ); #endif diff --git a/src/openocd-usb.cfg b/src/openocd-usb.cfg index d24aa09..a55e0cf 100644 --- a/src/openocd-usb.cfg +++ b/src/openocd-usb.cfg @@ -4,10 +4,11 @@ # http://www.hs-augsburg.de/~hhoegl/proj/usbjtag/usbjtag.html # -interface ft2232 -ft2232_vid_pid 0x15ba 0x0003 -ft2232_device_desc "Olimex OpenOCD JTAG" -ft2232_layout "olimex-jtag" +#interface ft2232 +interface ftdi +#ft2232_vid_pid 0x15ba 0x0003 +#ft2232_device_desc "Olimex OpenOCD JTAG" +#ft2232_layout "olimex-jtag" #interface ft2232 diff --git a/src/power.c b/src/power.c index 848159c..f769a7a 100644 --- a/src/power.c +++ b/src/power.c @@ -15,12 +15,12 @@ * USB [enabled via usb_init] * PWM1 */ -void power_init() { - LPC_SC->PCONP = BV(PCSSP0) - | BV(PCTIM3) - | BV(PCRTC) - | BV(PCGPIO) - | BV(PCPWM1) -// | BV(PCUSB) - ; +void power_init() +{ + LPC_SC->PCONP = BV( PCSSP0 ) + | BV( PCTIM3 ) + | BV( PCRTC ) + | BV( PCGPIO ) + | BV( PCPWM1 ) + | BV( PCUSB ); } diff --git a/src/power.h b/src/power.h index 65d3cac..e283c57 100644 --- a/src/power.h +++ b/src/power.h @@ -5,7 +5,7 @@ #include "bits.h" -#define PCUART0 (3) +#define PCUART0 (3) #define PCUART1 (4) #define PCUART2 (24) #define PCUART3 (25) @@ -38,6 +38,6 @@ #define PCQEI (18) #define PCGPIO (15) -void power_init(void); +void power_init( void ); #endif diff --git a/src/printf.c b/src/printf.c index 861c03d..fa057be 100644 --- a/src/printf.c +++ b/src/printf.c @@ -61,231 +61,296 @@ static char *outptr; static int maxlen; /* printf */ -static void outchar(char x) { - if (maxlen) { - maxlen--; - outfunc(x); - outlength++; - } +static void outchar( char x ) +{ + if ( maxlen ) + { + maxlen--; + outfunc( x ); + outlength++; + } } /* sprintf */ -static void outstr(char x) { - if (maxlen) { - maxlen--; - *outptr++ = x; - outlength++; - } +static void outstr( char x ) +{ + if ( maxlen ) + { + maxlen--; + *outptr++ = x; + outlength++; + } } -static int internal_nprintf(void (*output_function)(char c), const char *fmt, va_list ap) { - unsigned int width; - unsigned int flags; - unsigned int base = 0; - char *ptr = NULL; +static int internal_nprintf( void ( *output_function )( char c ), const char *fmt, va_list ap ) +{ + unsigned int width; + unsigned int flags; + unsigned int base = 0; + char *ptr = NULL; - outlength = 0; + outlength = 0; - while (*fmt) { - while (1) { - if (*fmt == 0) - goto end; + while ( *fmt ) + { + while ( 1 ) + { + if ( *fmt == 0 ) + { + goto end; + } - if (*fmt == '%') { - fmt++; - if (*fmt != '%') - break; - } + if ( *fmt == '%' ) + { + fmt++; - output_function(*fmt++); - } + if ( *fmt != '%' ) + { + break; + } + } - flags = 0; - width = 0; - - /* read all flags */ - do { - if (flags < FLAG_WIDTH) { - switch (*fmt) { - case '0': - flags |= FLAG_ZEROPAD; - continue; - - case '-': - flags |= FLAG_LEFTADJ; - continue; - - case ' ': - flags |= FLAG_BLANK; - continue; - - case '+': - flags |= FLAG_FORCESIGN; - continue; - } - } - - if (flags < FLAG_LONG) { - if (*fmt >= '0' && *fmt <= '9') { - unsigned char tmp = *fmt - '0'; - width = 10*width + tmp; - flags |= FLAG_WIDTH; - continue; + output_function( *fmt++ ); } - if (*fmt == 'h') - continue; + flags = 0; + width = 0; - if (*fmt == 'l') { - flags |= FLAG_LONG; - continue; + /* read all flags */ + do + { + if ( flags < FLAG_WIDTH ) + { + switch ( *fmt ) + { + case '0': + flags |= FLAG_ZEROPAD; + continue; + + case '-': + flags |= FLAG_LEFTADJ; + continue; + + case ' ': + flags |= FLAG_BLANK; + continue; + + case '+': + flags |= FLAG_FORCESIGN; + continue; + } + } + + if ( flags < FLAG_LONG ) + { + if ( *fmt >= '0' && *fmt <= '9' ) + { + unsigned char tmp = *fmt - '0'; + width = 10 * width + tmp; + flags |= FLAG_WIDTH; + continue; + } + + if ( *fmt == 'h' ) + { + continue; + } + + if ( *fmt == 'l' ) + { + flags |= FLAG_LONG; + continue; + } + } + + break; } - } + while ( *fmt++ ); - break; - } while (*fmt++); + /* Strings */ + if ( *fmt == 'c' || *fmt == 's' ) + { + switch ( *fmt ) + { + case 'c': + buffer[0] = va_arg( ap, int ); + ptr = buffer; + break; - /* Strings */ - if (*fmt == 'c' || *fmt == 's') { - switch (*fmt) { - case 'c': - buffer[0] = va_arg(ap, int); - ptr = buffer; - break; + case 's': + ptr = va_arg( ap, char * ); + break; + } - case 's': - ptr = va_arg(ap, char *); - break; - } + goto output; + } - goto output; - } + /* Numbers */ + switch ( *fmt ) + { + case 'u': + flags |= FLAG_UNSIGNED; - /* Numbers */ - switch (*fmt) { - case 'u': - flags |= FLAG_UNSIGNED; - case 'd': - base = 10; - break; + case 'd': + base = 10; + break; - case 'o': - base = 8; - flags |= FLAG_UNSIGNED; - break; + case 'o': + base = 8; + flags |= FLAG_UNSIGNED; + break; - case 'p': // pointer - output_function('0'); - output_function('x'); - width -= 2; - case 'x': - case 'X': - base = 16; - flags |= FLAG_UNSIGNED; - break; - } + case 'p': // pointer + output_function( '0' ); + output_function( 'x' ); + width -= 2; - unsigned int num; + case 'x': + case 'X': + base = 16; + flags |= FLAG_UNSIGNED; + break; + } - if (!(flags & FLAG_UNSIGNED)) { - int tmp = va_arg(ap, int); - if (tmp < 0) { - num = -tmp; - flags |= FLAG_NEGATIVE; - } else - num = tmp; - } else { - num = va_arg(ap, unsigned int); - } + unsigned int num; - /* Convert number into buffer */ - ptr = buffer + sizeof(buffer); - *--ptr = 0; - do { - *--ptr = hexdigits[num % base]; - num /= base; - } while (num != 0); + if ( !( flags & FLAG_UNSIGNED ) ) + { + int tmp = va_arg( ap, int ); - /* Sign */ - if (flags & FLAG_NEGATIVE) { - output_function('-'); - width--; - } else if (flags & FLAG_FORCESIGN) { - output_function('+'); - width--; - } else if (flags & FLAG_BLANK) { - output_function(' '); - width--; - } - - output: - /* left padding */ - if ((flags & FLAG_WIDTH) && !(flags & FLAG_LEFTADJ)) { - while (strlen(ptr) < width) { - if (flags & FLAG_ZEROPAD) - output_function('0'); + if ( tmp < 0 ) + { + num = -tmp; + flags |= FLAG_NEGATIVE; + } + else + { + num = tmp; + } + } else - output_function(' '); - width--; - } + { + num = va_arg( ap, unsigned int ); + } + + /* Convert number into buffer */ + ptr = buffer + sizeof( buffer ); + *--ptr = 0; + + do + { + *--ptr = hexdigits[num % base]; + num /= base; + } + while ( num != 0 ); + + /* Sign */ + if ( flags & FLAG_NEGATIVE ) + { + output_function( '-' ); + width--; + } + else if ( flags & FLAG_FORCESIGN ) + { + output_function( '+' ); + width--; + } + else if ( flags & FLAG_BLANK ) + { + output_function( ' ' ); + width--; + } + +output: + + /* left padding */ + if ( ( flags & FLAG_WIDTH ) && !( flags & FLAG_LEFTADJ ) ) + { + while ( strlen( ptr ) < width ) + { + if ( flags & FLAG_ZEROPAD ) + { + output_function( '0' ); + } + else + { + output_function( ' ' ); + } + + width--; + } + } + + /* data */ + while ( *ptr ) + { + output_function( *ptr++ ); + + if ( width ) + { + width--; + } + } + + /* right padding */ + if ( flags & FLAG_WIDTH ) + { + while ( width ) + { + output_function( ' ' ); + width--; + } + } + + fmt++; } - /* data */ - while (*ptr) { - output_function(*ptr++); - if (width) - width--; - } - - /* right padding */ - if (flags & FLAG_WIDTH) { - while (width) { - output_function(' '); - width--; - } - } - - fmt++; - } - - end: - return outlength; +end: + return outlength; } -int printf(const char *format, ...) { - va_list ap; - int res; +int printf( const char *format, ... ) +{ + va_list ap; + int res; - maxlen = -1; - va_start(ap, format); - res = internal_nprintf(outchar, format, ap); - va_end(ap); - return res; + maxlen = -1; + va_start( ap, format ); + res = internal_nprintf( outchar, format, ap ); + va_end( ap ); + return res; } -int snprintf(char *str, size_t size, const char *format, ...) { - va_list ap; - int res; +int snprintf( char *str, size_t size, const char *format, ... ) +{ + va_list ap; + int res; - maxlen = size; - outptr = str; - va_start(ap, format); - res = internal_nprintf(outstr, format, ap); - va_end(ap); - if (res < size) - str[res] = 0; - return res; + maxlen = size; + outptr = str; + va_start( ap, format ); + res = internal_nprintf( outstr, format, ap ); + va_end( ap ); + + if ( res < size ) + { + str[res] = 0; + } + + return res; } /* Required for gcc compatibility */ -int puts(const char *str) { - uart_puts(str); - uart_putc('\n'); - return 0; +int puts( const char *str ) +{ + uart_puts( str ); + uart_putc( '\n' ); + return 0; } #undef putchar -int putchar(int c) { - uart_putc(c); - return 0; +int putchar( int c ) +{ + uart_putc( c ); + return 0; } diff --git a/src/rle.c b/src/rle.c index 74e3d6d..2434df5 100644 --- a/src/rle.c +++ b/src/rle.c @@ -2,65 +2,92 @@ #include "rle.h" #include "fileops.h" -uint8_t rle_file_getc() { - static uint16_t rle_filled = 0; - static uint8_t data; - if(!rle_filled) { - data = file_getc(); - switch(data) { - case RLE_RUN: +uint8_t rle_file_getc() +{ + static uint16_t rle_filled = 0; + static uint8_t data; + + if ( !rle_filled ) + { data = file_getc(); - rle_filled = file_getc()-1; - break; - case RLE_RUNLONG: - data = file_getc(); - rle_filled = file_getc(); - rle_filled |= file_getc() << 8; + + switch ( data ) + { + case RLE_RUN: + data = file_getc(); + rle_filled = file_getc() - 1; + break; + + case RLE_RUNLONG: + data = file_getc(); + rle_filled = file_getc(); + rle_filled |= file_getc() << 8; + rle_filled--; + break; + + case RLE_ESC: + data = file_getc(); + break; + } + } + else + { rle_filled--; - break; - case RLE_ESC: - data = file_getc(); - break; } - } else { - rle_filled--; - } - if(file_status || file_res) rle_filled = 0; - return data; + + if ( file_status || file_res ) + { + rle_filled = 0; + } + + return data; } -void rle_mem_init(const uint8_t* address, uint32_t len) { - rle_mem_ptr = address; - rle_mem_endptr = address+len; - rle_state = 0; +void rle_mem_init( const uint8_t *address, uint32_t len ) +{ + rle_mem_ptr = address; + rle_mem_endptr = address + len; + rle_state = 0; } -uint8_t rle_mem_getc() { - static uint16_t rle_mem_filled = 0; - static uint8_t rle_mem_data; - if(!rle_mem_filled) { - rle_mem_data = *(rle_mem_ptr++); - switch(rle_mem_data) { - case RLE_RUN: - rle_mem_data = *(rle_mem_ptr)++; - rle_mem_filled = *(rle_mem_ptr)++ - 1; - break; - case RLE_RUNLONG: - rle_mem_data = *(rle_mem_ptr)++; - rle_mem_filled = *(rle_mem_ptr)++; - rle_mem_filled |= *(rle_mem_ptr)++ << 8; +uint8_t rle_mem_getc() +{ + static uint16_t rle_mem_filled = 0; + static uint8_t rle_mem_data; + + if ( !rle_mem_filled ) + { + rle_mem_data = *( rle_mem_ptr++ ); + + switch ( rle_mem_data ) + { + case RLE_RUN: + rle_mem_data = *( rle_mem_ptr )++; + rle_mem_filled = *( rle_mem_ptr )++ - 1; + break; + + case RLE_RUNLONG: + rle_mem_data = *( rle_mem_ptr )++; + rle_mem_filled = *( rle_mem_ptr )++; + rle_mem_filled |= *( rle_mem_ptr )++ << 8; + rle_mem_filled--; + break; + + case RLE_ESC: + rle_mem_data = *( rle_mem_ptr )++; + break; + } + } + else + { rle_mem_filled--; - break; - case RLE_ESC: - rle_mem_data = *(rle_mem_ptr)++; - break; } - } else { - rle_mem_filled--; - } - if(rle_mem_ptr>=rle_mem_endptr){ - rle_mem_filled = 0; - rle_state = 1; - } - return rle_mem_data; + + if ( rle_mem_ptr >= rle_mem_endptr ) + { + rle_mem_filled = 0; + rle_state = 1; + } + + return rle_mem_data; } diff --git a/src/rle.h b/src/rle.h index 9747043..182f6cd 100644 --- a/src/rle.h +++ b/src/rle.h @@ -7,9 +7,9 @@ #define RLE_RUN (0x5b) #define RLE_RUNLONG (0x77) -uint8_t rle_file_getc(void); -uint8_t rle_mem_getc(void); -void rle_mem_init(const uint8_t *address, uint32_t len); +uint8_t rle_file_getc( void ); +uint8_t rle_mem_getc( void ); +void rle_mem_init( const uint8_t *address, uint32_t len ); const uint8_t *rle_mem_ptr; const uint8_t *rle_mem_endptr; uint8_t rle_state; diff --git a/src/rtc.c b/src/rtc.c index f060945..e5aa017 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -11,125 +11,149 @@ rtcstate_t rtc_state; #define CLKEN 0 #define CTCRST 1 -uint8_t rtc_isvalid(void) { - if(LPC_RTC->GPREG0 == RTC_MAGIC) { - return RTC_OK; - } - return RTC_INVALID; +uint8_t rtc_isvalid( void ) +{ + if ( LPC_RTC->GPREG0 == RTC_MAGIC ) + { + return RTC_OK; + } + + return RTC_INVALID; } -void rtc_init(void) { - if (LPC_RTC->CCR & BV(CLKEN)) { - rtc_state = RTC_OK; - } else { - rtc_state = RTC_INVALID; - } +void rtc_init( void ) +{ + if ( LPC_RTC->CCR & BV( CLKEN ) ) + { + rtc_state = RTC_OK; + } + else + { + rtc_state = RTC_INVALID; + } } -void read_rtc(struct tm *time) { - do { - time->tm_sec = LPC_RTC->SEC; - time->tm_min = LPC_RTC->MIN; - time->tm_hour = LPC_RTC->HOUR; - time->tm_mday = LPC_RTC->DOM; - time->tm_mon = LPC_RTC->MONTH; - time->tm_year = LPC_RTC->YEAR; - time->tm_wday = LPC_RTC->DOW; - } while (time->tm_sec != LPC_RTC->SEC); +void read_rtc( struct tm *time ) +{ + do + { + time->tm_sec = LPC_RTC->SEC; + time->tm_min = LPC_RTC->MIN; + time->tm_hour = LPC_RTC->HOUR; + time->tm_mday = LPC_RTC->DOM; + time->tm_mon = LPC_RTC->MONTH; + time->tm_year = LPC_RTC->YEAR; + time->tm_wday = LPC_RTC->DOW; + } + while ( time->tm_sec != LPC_RTC->SEC ); } -uint8_t calc_weekday(struct tm *time) { - int month = time->tm_mon; - int year = time->tm_year; - int day = time->tm_mday; +uint8_t calc_weekday( struct tm *time ) +{ + int month = time->tm_mon; + int year = time->tm_year; + int day = time->tm_mday; - /* Variation of Sillke for the Gregorian calendar. - * http://www.mathematik.uni-bielefeld.de/~sillke/ALGORITHMS/calendar/weekday.c */ - if (month <= 2) { - month += 10; - year--; - } else month -= 2; - return (83*month/32 + day + year + year/4 - year/100 + year/400) % 7; + /* Variation of Sillke for the Gregorian calendar. + * http://www.mathematik.uni-bielefeld.de/~sillke/ALGORITHMS/calendar/weekday.c */ + if ( month <= 2 ) + { + month += 10; + year--; + } + else + { + month -= 2; + } + + return ( 83 * month / 32 + day + year + year / 4 - year / 100 + year / 400 ) % 7; } -void set_rtc(struct tm *time) { - LPC_RTC->CCR = BV(CTCRST); - LPC_RTC->SEC = time->tm_sec; - LPC_RTC->MIN = time->tm_min; - LPC_RTC->HOUR = time->tm_hour; - LPC_RTC->DOM = time->tm_mday; - LPC_RTC->MONTH = time->tm_mon; - LPC_RTC->YEAR = time->tm_year; - LPC_RTC->DOW = calc_weekday(time); - LPC_RTC->CCR = BV(CLKEN); - LPC_RTC->GPREG0 = RTC_MAGIC; +void set_rtc( struct tm *time ) +{ + LPC_RTC->CCR = BV( CTCRST ); + LPC_RTC->SEC = time->tm_sec; + LPC_RTC->MIN = time->tm_min; + LPC_RTC->HOUR = time->tm_hour; + LPC_RTC->DOM = time->tm_mday; + LPC_RTC->MONTH = time->tm_mon; + LPC_RTC->YEAR = time->tm_year; + LPC_RTC->DOW = calc_weekday( time ); + LPC_RTC->CCR = BV( CLKEN ); + LPC_RTC->GPREG0 = RTC_MAGIC; } -void invalidate_rtc() { - LPC_RTC->GPREG0 = 0; +void invalidate_rtc() +{ + LPC_RTC->GPREG0 = 0; } -uint32_t get_fattime(void) { - struct tm time; +uint32_t get_fattime( void ) +{ + struct tm time; - read_rtc(&time); - return ((uint32_t)time.tm_year-1980) << 25 | - ((uint32_t)time.tm_mon) << 21 | - ((uint32_t)time.tm_mday) << 16 | - ((uint32_t)time.tm_hour) << 11 | - ((uint32_t)time.tm_min) << 5 | - ((uint32_t)time.tm_sec) >> 1; + read_rtc( &time ); + return ( ( uint32_t )time.tm_year - 1980 ) << 25 | + ( ( uint32_t )time.tm_mon ) << 21 | + ( ( uint32_t )time.tm_mday ) << 16 | + ( ( uint32_t )time.tm_hour ) << 11 | + ( ( uint32_t )time.tm_min ) << 5 | + ( ( uint32_t )time.tm_sec ) >> 1; } -uint64_t get_bcdtime(void) { - struct tm time; - read_rtc(&time); - uint16_t year = time.tm_year; +uint64_t get_bcdtime( void ) +{ + struct tm time; + read_rtc( &time ); + uint16_t year = time.tm_year; - return ((uint64_t)(time.tm_wday % 7) << 56) - |((uint64_t)((year / 1000) % 10) << 52) - |((uint64_t)((year / 100) % 10) << 48) - |((uint64_t)((year / 10) % 10) << 44) - |((uint64_t)(year % 10) << 40) - |((uint64_t)(time.tm_mon / 10) << 36) - |((uint64_t)(time.tm_mon % 10) << 32) - |((time.tm_mday / 10) << 28) - |((time.tm_mday % 10) << 24) - |((time.tm_hour / 10) << 20) - |((time.tm_hour % 10) << 16) - |((time.tm_min / 10) << 12) - |((time.tm_min % 10) << 8) - |((time.tm_sec / 10) << 4) - |(time.tm_sec % 10); + return ( ( uint64_t )( time.tm_wday % 7 ) << 56 ) + | ( ( uint64_t )( ( year / 1000 ) % 10 ) << 52 ) + | ( ( uint64_t )( ( year / 100 ) % 10 ) << 48 ) + | ( ( uint64_t )( ( year / 10 ) % 10 ) << 44 ) + | ( ( uint64_t )( year % 10 ) << 40 ) + | ( ( uint64_t )( time.tm_mon / 10 ) << 36 ) + | ( ( uint64_t )( time.tm_mon % 10 ) << 32 ) + | ( ( time.tm_mday / 10 ) << 28 ) + | ( ( time.tm_mday % 10 ) << 24 ) + | ( ( time.tm_hour / 10 ) << 20 ) + | ( ( time.tm_hour % 10 ) << 16 ) + | ( ( time.tm_min / 10 ) << 12 ) + | ( ( time.tm_min % 10 ) << 8 ) + | ( ( time.tm_sec / 10 ) << 4 ) + | ( time.tm_sec % 10 ); } -void set_bcdtime(uint64_t btime) { - struct tm time; - time.tm_sec = (btime & 0xf) + ((btime >> 4) & 0xf) * 10; - time.tm_min = ((btime >> 8) & 0xf) + ((btime >> 12) & 0xf) * 10; - time.tm_hour = ((btime >> 16) & 0xf) + ((btime >> 20) & 0xf) * 10; - time.tm_mday = ((btime >> 24) & 0xf) + ((btime >> 28) & 0xf) * 10; - time.tm_mon = ((btime >> 32) & 0xf) + ((btime >> 36) & 0xf) * 10; - time.tm_year = ((btime >> 40) & 0xf) + ((btime >> 44) & 0xf) * 10 - + ((btime >> 48) & 0xf) * 100 + ((btime >> 52) & 0xf) * 1000; - printtime(&time); - set_rtc(&time); +void set_bcdtime( uint64_t btime ) +{ + struct tm time; + time.tm_sec = ( btime & 0xf ) + ( ( btime >> 4 ) & 0xf ) * 10; + time.tm_min = ( ( btime >> 8 ) & 0xf ) + ( ( btime >> 12 ) & 0xf ) * 10; + time.tm_hour = ( ( btime >> 16 ) & 0xf ) + ( ( btime >> 20 ) & 0xf ) * 10; + time.tm_mday = ( ( btime >> 24 ) & 0xf ) + ( ( btime >> 28 ) & 0xf ) * 10; + time.tm_mon = ( ( btime >> 32 ) & 0xf ) + ( ( btime >> 36 ) & 0xf ) * 10; + time.tm_year = ( ( btime >> 40 ) & 0xf ) + ( ( btime >> 44 ) & 0xf ) * 10 + + ( ( btime >> 48 ) & 0xf ) * 100 + ( ( btime >> 52 ) & 0xf ) * 1000; + printtime( &time ); + set_rtc( &time ); } -void printtime(struct tm *time) { - printf("%04d-%02d-%02d %02d:%02d:%02d\n", time->tm_year, time->tm_mon, - time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec); +void printtime( struct tm *time ) +{ + printf( "%04d-%02d-%02d %02d:%02d:%02d\n", time->tm_year, time->tm_mon, + time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec ); } -void testbattery() { - printf("%lx\n", LPC_RTC->GPREG0); - LPC_RTC->GPREG0 = RTC_MAGIC; - printf("%lx\n", LPC_RTC->GPREG0); - LPC_RTC->CCR = 0; - BITBAND(LPC_SC->PCONP, PCRTC) = 0; - delay_ms(20000); - BITBAND(LPC_SC->PCONP, PCRTC) = 1; - printf("%lx\n", LPC_RTC->GPREG0); - delay_ms(20); - LPC_RTC->CCR = BV(CLKEN); +void testbattery() +{ + printf( "%lx\n", LPC_RTC->GPREG0 ); + LPC_RTC->GPREG0 = RTC_MAGIC; + printf( "%lx\n", LPC_RTC->GPREG0 ); + LPC_RTC->CCR = 0; + BITBAND( LPC_SC->PCONP, PCRTC ) = 0; + delay_ms( 20000 ); + BITBAND( LPC_SC->PCONP, PCRTC ) = 1; + printf( "%lx\n", LPC_RTC->GPREG0 ); + delay_ms( 20 ); + LPC_RTC->CCR = BV( CLKEN ); } diff --git a/src/rtc.h b/src/rtc.h index 4e52a96..8e601ec 100644 --- a/src/rtc.h +++ b/src/rtc.h @@ -29,50 +29,52 @@ #include -typedef enum { - RTC_NOT_FOUND, /* No RTC present */ - RTC_INVALID, /* RTC present, but contents invalid */ - RTC_OK /* RTC present and working */ +typedef enum +{ + RTC_NOT_FOUND, /* No RTC present */ + RTC_INVALID, /* RTC present, but contents invalid */ + RTC_OK /* RTC present and working */ } rtcstate_t; -struct tm { - uint8_t tm_sec; // 0..59 - uint8_t tm_min; // 0..59 - uint8_t tm_hour; // 0..23 - uint8_t tm_mday; // 1..[28..31] - uint8_t tm_mon; // 0..11 - uint16_t tm_year; // since 0 A.D. - uint8_t tm_wday; // 0 to 6, sunday is 6 - // A Unix struct tm has a few more fields we don't need in this application +struct tm +{ + uint8_t tm_sec; // 0..59 + uint8_t tm_min; // 0..59 + uint8_t tm_hour; // 0..23 + uint8_t tm_mday; // 1..[28..31] + uint8_t tm_mon; // 0..11 + uint16_t tm_year; // since 0 A.D. + uint8_t tm_wday; // 0 to 6, sunday is 6 + // A Unix struct tm has a few more fields we don't need in this application }; #define RTC_MAGIC (0x43545253L) extern rtcstate_t rtc_state; -void rtc_init(void); +void rtc_init( void ); /* return RTC valid state based on magic token in backup register */ -uint8_t rtc_isvalid(void); +uint8_t rtc_isvalid( void ); /* Return current time in struct tm */ -void read_rtc(struct tm *time); +void read_rtc( struct tm *time ); /* Set time from struct tm, also sets RTC valid */ -void set_rtc(struct tm *time); +void set_rtc( struct tm *time ); /* Set RTC invalid */ -void invalidate_rtc(void); +void invalidate_rtc( void ); /* get current time in 60-bit BCD format (WYYYYMMDDHHMMSS) (W=DOW) */ -uint64_t get_bcdtime(void); +uint64_t get_bcdtime( void ); /* set current time from 56-bit BCD format (YYYYMMDDHHMMSS) DOW is calculated */ -void set_bcdtime(uint64_t btime); +void set_bcdtime( uint64_t btime ); /* print the time to the console */ -void printtime(struct tm *time); +void printtime( struct tm *time ); -void testbattery(void); +void testbattery( void ); #endif diff --git a/src/sdnative.c b/src/sdnative.c index 8d3ea09..4cb184f 100644 --- a/src/sdnative.c +++ b/src/sdnative.c @@ -109,12 +109,12 @@ - CMD55: 0x77 0x00 0x00 0x00 0x00 0x65 */ -uint8_t cmd[6]={0,0,0,0,0,0}; +uint8_t cmd[6] = {0, 0, 0, 0, 0, 0}; uint8_t rsp[17]; uint8_t csd[17]; uint8_t cid[17]; diskinfo0_t di; -uint8_t ccs=0; +uint8_t ccs = 0; uint32_t rca; enum trans_state { TRANS_NONE = 0, TRANS_READ, TRANS_WRITE, TRANS_MID }; @@ -137,126 +137,163 @@ volatile int sd_changed; * is assumed to be MSB first, passing 0 for start will read starting * from the highest-value bit of the first byte of the buffer. */ -static uint32_t getbits(void *buffer, uint16_t start, int8_t bits) { - uint8_t *buf = buffer; - uint32_t result = 0; +static uint32_t getbits( void *buffer, uint16_t start, int8_t bits ) +{ + uint8_t *buf = buffer; + uint32_t result = 0; - if ((start % 8) != 0) { - /* Unaligned start */ - result += buf[start / 8] & (0xff >> (start % 8)); - bits -= 8 - (start % 8); - start += 8 - (start % 8); - } - while (bits >= 8) { - result = (result << 8) + buf[start / 8]; - start += 8; - bits -= 8; - } - if (bits > 0) { - result = result << bits; - result = result + (buf[start / 8] >> (8-bits)); - } else if (bits < 0) { - /* Fraction of a single byte */ - result = result >> -bits; - } - return result; -} - -void sdn_checkinit(BYTE drv) { - if(disk_state == DISK_CHANGED) { - disk_initialize(drv); - } -} - -uint8_t* sdn_getcid() { - sdn_checkinit(0); - return cid; -} - -static inline void wiggle_slow_pos(uint16_t times) { - while(times--) { - delay_us(2); - BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1; - delay_us(2); - BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1; - } -} - -static inline void wiggle_slow_neg(uint16_t times) { - while(times--) { - delay_us(2); - BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1; - delay_us(2); - BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1; - } -} - -static inline void wiggle_fast_pos(uint16_t times) { - while(times--) { - BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1; - BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1; - } -} - -static inline void wiggle_fast_neg(uint16_t times) { - while(times--) { - BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1; - BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1; - } -} - -static inline void wiggle_fast_neg1(void) { - BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1; - BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1; -} - -static inline void wiggle_fast_pos1(void) { - BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1; - BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1; -} - - -int get_and_check_datacrc(uint8_t *buf) { - uint16_t crc0=0, crc1=0, crc2=0, crc3=0; - uint16_t sdcrc0=0, sdcrc1=0, sdcrc2=0, sdcrc3=0; - uint8_t d0=0, d1=0, d2=0, d3=0; - uint8_t datdata; - uint16_t datcnt; - /* get crcs from card */ - for (datcnt=0; datcnt < 16; datcnt++) { - datdata = SD_DAT; - wiggle_fast_neg1(); - sdcrc0 = ((sdcrc0 << 1) & 0xfffe) | ((datdata >> 3) & 0x0001); - sdcrc1 = ((sdcrc1 << 1) & 0xfffe) | ((datdata >> 2) & 0x0001); - sdcrc2 = ((sdcrc2 << 1) & 0xfffe) | ((datdata >> 1) & 0x0001); - sdcrc3 = ((sdcrc3 << 1) & 0xfffe) | ((datdata >> 0) & 0x0001); - } - wiggle_fast_neg1(); - /* calc crcs from data */ - for (datcnt=0; datcnt < 512; datcnt++) { - d0 = ((d0 << 2) & 0xfc) | ((buf[datcnt] >> 6) & 0x02) | ((buf[datcnt] >> 3) & 0x01) ; - d1 = ((d1 << 2) & 0xfc) | ((buf[datcnt] >> 5) & 0x02) | ((buf[datcnt] >> 2) & 0x01) ; - d2 = ((d2 << 2) & 0xfc) | ((buf[datcnt] >> 4) & 0x02) | ((buf[datcnt] >> 1) & 0x01) ; - d3 = ((d3 << 2) & 0xfc) | ((buf[datcnt] >> 3) & 0x02) | ((buf[datcnt] >> 0) & 0x01) ; - if((datcnt % 4) == 3) { - crc0 = crc_xmodem_update(crc0, d0); - crc1 = crc_xmodem_update(crc1, d1); - crc2 = crc_xmodem_update(crc2, d2); - crc3 = crc_xmodem_update(crc3, d3); + if ( ( start % 8 ) != 0 ) + { + /* Unaligned start */ + result += buf[start / 8] & ( 0xff >> ( start % 8 ) ); + bits -= 8 - ( start % 8 ); + start += 8 - ( start % 8 ); } - } - if((crc0 != sdcrc0) || (crc1 != sdcrc1) || (crc2 != sdcrc2) || (crc3 != sdcrc3)) { - printf("CRC mismatch\nSDCRC CRC\n %04x %04x\n %04x %04x\n %04x %04x\n %04x %04x\n", sdcrc0, crc0, sdcrc1, crc1, sdcrc2, crc2, sdcrc3, crc3); - return 1; - } - return 0; + + while ( bits >= 8 ) + { + result = ( result << 8 ) + buf[start / 8]; + start += 8; + bits -= 8; + } + + if ( bits > 0 ) + { + result = result << bits; + result = result + ( buf[start / 8] >> ( 8 - bits ) ); + } + else if ( bits < 0 ) + { + /* Fraction of a single byte */ + result = result >> -bits; + } + + return result; } -static inline void wait_busy(void) { - while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) { +void sdn_checkinit( BYTE drv ) +{ + if ( disk_state == DISK_CHANGED ) + { + disk_initialize( drv ); + } +} + +uint8_t *sdn_getcid() +{ + sdn_checkinit( 0 ); + return cid; +} + +static inline void wiggle_slow_pos( uint16_t times ) +{ + while ( times-- ) + { + delay_us( 2 ); + BITBAND( SD_CLKREG->FIOSET, SD_CLKPIN ) = 1; + delay_us( 2 ); + BITBAND( SD_CLKREG->FIOCLR, SD_CLKPIN ) = 1; + } +} + +static inline void wiggle_slow_neg( uint16_t times ) +{ + while ( times-- ) + { + delay_us( 2 ); + BITBAND( SD_CLKREG->FIOCLR, SD_CLKPIN ) = 1; + delay_us( 2 ); + BITBAND( SD_CLKREG->FIOSET, SD_CLKPIN ) = 1; + } +} + +static inline void wiggle_fast_pos( uint16_t times ) +{ + while ( times-- ) + { + BITBAND( SD_CLKREG->FIOSET, SD_CLKPIN ) = 1; + BITBAND( SD_CLKREG->FIOCLR, SD_CLKPIN ) = 1; + } +} + +static inline void wiggle_fast_neg( uint16_t times ) +{ + while ( times-- ) + { + BITBAND( SD_CLKREG->FIOCLR, SD_CLKPIN ) = 1; + BITBAND( SD_CLKREG->FIOSET, SD_CLKPIN ) = 1; + } +} + +static inline void wiggle_fast_neg1( void ) +{ + BITBAND( SD_CLKREG->FIOCLR, SD_CLKPIN ) = 1; + BITBAND( SD_CLKREG->FIOSET, SD_CLKPIN ) = 1; +} + +static inline void wiggle_fast_pos1( void ) +{ + BITBAND( SD_CLKREG->FIOSET, SD_CLKPIN ) = 1; + BITBAND( SD_CLKREG->FIOCLR, SD_CLKPIN ) = 1; +} + + +int get_and_check_datacrc( uint8_t *buf ) +{ + uint16_t crc0 = 0, crc1 = 0, crc2 = 0, crc3 = 0; + uint16_t sdcrc0 = 0, sdcrc1 = 0, sdcrc2 = 0, sdcrc3 = 0; + uint8_t d0 = 0, d1 = 0, d2 = 0, d3 = 0; + uint8_t datdata; + uint16_t datcnt; + + /* get crcs from card */ + for ( datcnt = 0; datcnt < 16; datcnt++ ) + { + datdata = SD_DAT; + wiggle_fast_neg1(); + sdcrc0 = ( ( sdcrc0 << 1 ) & 0xfffe ) | ( ( datdata >> 3 ) & 0x0001 ); + sdcrc1 = ( ( sdcrc1 << 1 ) & 0xfffe ) | ( ( datdata >> 2 ) & 0x0001 ); + sdcrc2 = ( ( sdcrc2 << 1 ) & 0xfffe ) | ( ( datdata >> 1 ) & 0x0001 ); + sdcrc3 = ( ( sdcrc3 << 1 ) & 0xfffe ) | ( ( datdata >> 0 ) & 0x0001 ); + } + wiggle_fast_neg1(); - } - wiggle_fast_neg(4); + + /* calc crcs from data */ + for ( datcnt = 0; datcnt < 512; datcnt++ ) + { + d0 = ( ( d0 << 2 ) & 0xfc ) | ( ( buf[datcnt] >> 6 ) & 0x02 ) | ( ( buf[datcnt] >> 3 ) & 0x01 ) ; + d1 = ( ( d1 << 2 ) & 0xfc ) | ( ( buf[datcnt] >> 5 ) & 0x02 ) | ( ( buf[datcnt] >> 2 ) & 0x01 ) ; + d2 = ( ( d2 << 2 ) & 0xfc ) | ( ( buf[datcnt] >> 4 ) & 0x02 ) | ( ( buf[datcnt] >> 1 ) & 0x01 ) ; + d3 = ( ( d3 << 2 ) & 0xfc ) | ( ( buf[datcnt] >> 3 ) & 0x02 ) | ( ( buf[datcnt] >> 0 ) & 0x01 ) ; + + if ( ( datcnt % 4 ) == 3 ) + { + crc0 = crc_xmodem_update( crc0, d0 ); + crc1 = crc_xmodem_update( crc1, d1 ); + crc2 = crc_xmodem_update( crc2, d2 ); + crc3 = crc_xmodem_update( crc3, d3 ); + } + } + + if ( ( crc0 != sdcrc0 ) || ( crc1 != sdcrc1 ) || ( crc2 != sdcrc2 ) || ( crc3 != sdcrc3 ) ) + { + printf( "CRC mismatch\nSDCRC CRC\n %04x %04x\n %04x %04x\n %04x %04x\n %04x %04x\n", sdcrc0, crc0, sdcrc1, + crc1, sdcrc2, crc2, sdcrc3, crc3 ); + return 1; + } + + return 0; +} + +static inline void wait_busy( void ) +{ + while ( !( BITBAND( SD_DAT0REG->FIOPIN, SD_DAT0PIN ) ) ) + { + wiggle_fast_neg1(); + } + + wiggle_fast_neg( 4 ); } /* @@ -264,69 +301,97 @@ static inline void wait_busy(void) { send SD command and put response in rsp. returns length of response or 0 if there was no response */ -int send_command_slow(uint8_t* cmd, uint8_t* rsp){ - uint8_t shift, i=6; - int rsplen; - uint8_t cmdno = *cmd & 0x3f; - wiggle_slow_pos(5); - switch(*cmd & 0x3f) { +int send_command_slow( uint8_t *cmd, uint8_t *rsp ) +{ + uint8_t shift, i = 6; + int rsplen; + uint8_t cmdno = *cmd & 0x3f; + wiggle_slow_pos( 5 ); + + switch ( *cmd & 0x3f ) + { case 0: - rsplen = 0; - break; + rsplen = 0; + break; + case 2: case 9: case 10: - rsplen = 17; - break; + rsplen = 17; + break; + default: - rsplen = 6; - } - /* send command */ - BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1; - - while(i--) { - shift = 8; - do { - shift--; - uint8_t data = *cmd; - *cmd<<=1; - if(data&0x80) { - BITBAND(SD_CMDREG->FIOSET, SD_CMDPIN) = 1; - } else { - BITBAND(SD_CMDREG->FIOCLR, SD_CMDPIN) = 1; - } - wiggle_slow_pos(1); - } while (shift); - cmd++; - } - - wiggle_slow_pos(1); - BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 0; - - if(rsplen) { - uint16_t timeout=1000; - while((BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) && --timeout) { - wiggle_slow_neg(1); - } - if(!timeout) { - printf("CMD%d timed out\n", cmdno); - return 0; /* no response within timeout */ + rsplen = 6; } - i=rsplen; - while(i--) { - shift = 8; - uint8_t data=0; - do { - shift--; - data |= (BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) << shift; - wiggle_slow_neg(1); - } while (shift); - *rsp=data; - rsp++; + /* send command */ + BITBAND( SD_CMDREG->FIODIR, SD_CMDPIN ) = 1; + + while ( i-- ) + { + shift = 8; + + do + { + shift--; + uint8_t data = *cmd; + *cmd <<= 1; + + if ( data & 0x80 ) + { + BITBAND( SD_CMDREG->FIOSET, SD_CMDPIN ) = 1; + } + else + { + BITBAND( SD_CMDREG->FIOCLR, SD_CMDPIN ) = 1; + } + + wiggle_slow_pos( 1 ); + } + while ( shift ); + + cmd++; } - } - return rsplen; + + wiggle_slow_pos( 1 ); + BITBAND( SD_CMDREG->FIODIR, SD_CMDPIN ) = 0; + + if ( rsplen ) + { + uint16_t timeout = 1000; + + while ( ( BITBAND( SD_CMDREG->FIOPIN, SD_CMDPIN ) ) && --timeout ) + { + wiggle_slow_neg( 1 ); + } + + if ( !timeout ) + { + printf( "CMD%d timed out\n", cmdno ); + return 0; /* no response within timeout */ + } + + i = rsplen; + + while ( i-- ) + { + shift = 8; + uint8_t data = 0; + + do + { + shift--; + data |= ( BITBAND( SD_CMDREG->FIOPIN, SD_CMDPIN ) ) << shift; + wiggle_slow_neg( 1 ); + } + while ( shift ); + + *rsp = data; + rsp++; + } + } + + return rsplen; } @@ -335,809 +400,1141 @@ int send_command_slow(uint8_t* cmd, uint8_t* rsp){ send SD command and put response in rsp. returns length of response or 0 if there was no response */ -int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){ - uint8_t datshift=8, cmdshift, i=6; - uint8_t cmdno = *cmd & 0x3f; - int rsplen, dat=0, waitbusy=0, datcnt=512, j=0; - static int state=CMD_RSP; - wiggle_fast_pos(9); /* give the card >=8 cycles after last command */ - DBG_SD printf("send_command_fast: sending CMD%d; payload=%02x%02x%02x%02x%02x%02x...\n", cmdno, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5]); - switch(*cmd & 0x3f) { +int send_command_fast( uint8_t *cmd, uint8_t *rsp, uint8_t *buf ) +{ + uint8_t datshift = 8, cmdshift, i = 6; + uint8_t cmdno = *cmd & 0x3f; + int rsplen, dat = 0, waitbusy = 0, datcnt = 512, j = 0; + static int state = CMD_RSP; + wiggle_fast_pos( 9 ); /* give the card >=8 cycles after last command */ + DBG_SD printf( "send_command_fast: sending CMD%d; payload=%02x%02x%02x%02x%02x%02x...\n", cmdno, cmd[0], cmd[1], cmd[2], + cmd[3], cmd[4], cmd[5] ); + + switch ( *cmd & 0x3f ) + { case 0: - rsplen = 0; - break; + rsplen = 0; + break; + case 2: case 9: case 10: - rsplen = 17; - break; + rsplen = 17; + break; + case 12: - rsplen = 6; - waitbusy = 1; - break; + rsplen = 6; + waitbusy = 1; + break; + case 13: case 17: case 18: - dat = 1; + dat = 1; + default: - rsplen = 6; - } - if(dat && (buf==NULL) && !sd_offload) { - printf("send_command_fast error: buf is null but data transfer expected.\n"); - return 0; - } - /* send command */ - BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1; - - while(i--) { - uint8_t data = *cmd; - cmdshift = 8; - do { - cmdshift--; - if(data&0x80) { - BITBAND(SD_CMDREG->FIOSET, SD_CMDPIN) = 1; - } else { - BITBAND(SD_CMDREG->FIOCLR, SD_CMDPIN) = 1; - } - data<<=1; - wiggle_fast_pos1(); - } while (cmdshift); - cmd++; - } - - wiggle_fast_pos1(); - BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 0; - - if(rsplen) { - uint32_t timeout=200000; - /* wait for response */ - while((BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) && --timeout) { - wiggle_fast_neg1(); + rsplen = 6; } - if(!timeout) { - printf("CMD%d timed out\n", cmdno); - return 0; /* no response within timeout */ + + if ( dat && ( buf == NULL ) && !sd_offload ) + { + printf( "send_command_fast error: buf is null but data transfer expected.\n" ); + return 0; } - i=rsplen; - uint8_t cmddata=0, datdata=0; - while(i--) { /* process response */ - cmdshift = 8; - do { - if(dat) { - if(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) { - printf("data start during response\n"); - j=datcnt; - state=CMD_RSPDAT; - break; - } + + /* send command */ + BITBAND( SD_CMDREG->FIODIR, SD_CMDPIN ) = 1; + + while ( i-- ) + { + uint8_t data = *cmd; + cmdshift = 8; + + do + { + cmdshift--; + + if ( data & 0x80 ) + { + BITBAND( SD_CMDREG->FIOSET, SD_CMDPIN ) = 1; + } + else + { + BITBAND( SD_CMDREG->FIOCLR, SD_CMDPIN ) = 1; + } + + data <<= 1; + wiggle_fast_pos1(); } - cmdshift--; - cmddata |= (BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) << cmdshift; - wiggle_fast_neg1(); - } while (cmdshift); - if(state==CMD_RSPDAT)break; - *rsp=cmddata; - cmddata=0; - rsp++; + while ( cmdshift ); + + cmd++; } - if(state==CMD_RSPDAT) { /* process response+data */ - int startbit=1; - DBG_SD printf("processing rsp+data cmdshift=%d i=%d j=%d\n", cmdshift, i, j); - datshift=8; - while(1) { - cmdshift--; - cmddata |= (BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) << cmdshift; - if(!cmdshift) { - cmdshift=8; - *rsp=cmddata; - cmddata=0; - rsp++; - i--; - if(!i) { - DBG_SD printf("response end\n"); - if(j) state=CMD_DAT; /* response over, remaining data */ - break; - } - } - if(!startbit) { - datshift-=4; - datdata |= SD_DAT << datshift; - if(!datshift) { - datshift=8; - *buf=datdata; - datdata=0; - buf++; - j--; - if(!j) break; - } - } - startbit=0; - wiggle_fast_neg1(); - } - } - - if(dat && state != CMD_DAT) { /* response ended before data */ - BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1; - state=CMD_DAT; - j=datcnt; - datshift=8; - timeout=2000000; - DBG_SD printf("response over, waiting for data...\n"); - /* wait for data start bit on DAT0 */ - while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) { - wiggle_fast_neg1(); - } -// printf("%ld\n", timeout); - if(!timeout) printf("timed out!\n"); - wiggle_fast_neg1(); /* eat the start bit */ - if(sd_offload) { - if(sd_offload_partial) { - if(sd_offload_partial_start != 0) { - if(during_blocktrans == TRANS_MID) sd_offload_partial_start |= 0x8000; - } - if(sd_offload_partial_end != 512) { - sd_offload_partial_end |= 0x8000; - } - DBG_SD printf("new partial %d - %d\n", sd_offload_partial_start, sd_offload_partial_end); - fpga_set_sddma_range(sd_offload_partial_start, sd_offload_partial_end); - fpga_sddma(sd_offload_tgt, 1); -// sd_offload_partial=0; - last_offset=sd_offload_partial_end; - } else { - fpga_sddma(sd_offload_tgt, 0); - last_offset=0; - } - state=CMD_RSP; - return rsplen; - } - } - - if(state==CMD_DAT) { /* transfer rest of data */ - DBG_SD printf("remaining data: %d\n", j); - if(datshift==8) { - while(1) { - datdata |= SD_DAT << 4; - wiggle_fast_neg1(); - - datdata |= SD_DAT; - wiggle_fast_neg1(); - - *buf=datdata; - datdata=0; - buf++; - j--; - if(!j) break; - } - } else { - - while(1) { - datshift-=4; - datdata |= SD_DAT << datshift; - if(!datshift) { - datshift=8; - *buf=datdata; - datdata=0; - buf++; - j--; - if(!j) break; - } - wiggle_fast_neg1(); - } - } - } - if(dat) { -#ifdef CONFIG_SD_DATACRC - if(get_and_check_datacrc(buf-512)) { - return CRC_ERROR; - } -#else - /* eat the crcs */ - wiggle_fast_neg(17); -#endif - } - - if(waitbusy) { - DBG_SD printf("waitbusy after send_cmd\n"); - wait_busy(); - } - state=CMD_RSP; - } - rsp-=rsplen; - DBG_SD printf("send_command_fast: CMD%d response: %02x%02x%02x%02x%02x%02x\n", cmdno, rsp[0], rsp[1], rsp[2], rsp[3], rsp[4], rsp[5]); - BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1; - return rsplen; -} - - -static inline void make_crc7(uint8_t* cmd) { - cmd[5]=crc7update(0, cmd[0]); - cmd[5]=crc7update(cmd[5], cmd[1]); - cmd[5]=crc7update(cmd[5], cmd[2]); - cmd[5]=crc7update(cmd[5], cmd[3]); - cmd[5]=crc7update(cmd[5], cmd[4]); - cmd[5]=(cmd[5] << 1) | 1; -} - -int cmd_slow(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) { - uint8_t cmdbuf[6]; - cmdbuf[0] = 0x40 | cmd; - cmdbuf[1] = param >> 24; - cmdbuf[2] = param >> 16; - cmdbuf[3] = param >> 8; - cmdbuf[4] = param; - if(!crc) { - make_crc7(cmdbuf); - } else { - cmdbuf[5] = crc; - } - return send_command_slow(cmdbuf, rsp); -} - -int acmd_slow(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) { - if(!(cmd_slow(APP_CMD, rca, 0, NULL, rsp))) { - return 0; - } - return cmd_slow(cmd, param, crc, dat, rsp); -} - -int cmd_fast(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) { - uint8_t cmdbuf[6]; - cmdbuf[0] = 0x40 | cmd; - cmdbuf[1] = param >> 24; - cmdbuf[2] = param >> 16; - cmdbuf[3] = param >> 8; - cmdbuf[4] = param; - if(!crc) { - make_crc7(cmdbuf); - } else { - cmdbuf[5] = crc; - } - return send_command_fast(cmdbuf, rsp, dat); -} - -int acmd_fast(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) { - if(!(cmd_fast(APP_CMD, rca, 0, NULL, rsp))) { - return 0; - } - return cmd_fast(cmd, param, crc, dat, rsp); -} - -int stream_datablock(uint8_t *buf) { -// uint8_t datshift=8; - int j=512; - uint8_t datdata=0; - uint32_t timeout=1000000; - - DBG_SD printf("stream_datablock: wait for ready...\n"); - if(during_blocktrans != TRANS_MID) { - while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) { - wiggle_fast_neg1(); - } - DBG_SD if(!timeout) printf("timeout!\n"); - wiggle_fast_neg1(); /* eat the start bit */ - } - if(sd_offload) { - if(sd_offload_partial) { - if(sd_offload_partial_start != 0) { - if(during_blocktrans == TRANS_MID) sd_offload_partial_start |= 0x8000; - } - if(sd_offload_partial_end != 512) { - sd_offload_partial_end |= 0x8000; - } - DBG_SD printf("str partial %d - %d\n", sd_offload_partial_start, sd_offload_partial_end); - fpga_set_sddma_range(sd_offload_partial_start, sd_offload_partial_end); - fpga_sddma(sd_offload_tgt, 1); - } else { - fpga_sddma(sd_offload_tgt, 0); - } - } else { - while(1) { - datdata = SD_DAT << 4; - wiggle_fast_neg1(); - - datdata |= SD_DAT; - wiggle_fast_neg1(); - - *buf=datdata; - buf++; - j--; - if(!j) break; - } -#ifdef CONFIG_SD_DATACRC - return get_and_check_datacrc(buf-512); -#else - /* eat the crcs */ - wiggle_fast_neg(17); -#endif - } - return 0; -} - -void send_datablock(uint8_t *buf) { - uint16_t crc0=0, crc1=0, crc2=0, crc3=0, cnt=512; - uint8_t dat0=0, dat1=0, dat2=0, dat3=0, crcshift, datshift; - - wiggle_fast_pos1(); - BITBAND(SD_DAT0REG->FIODIR, SD_DAT0PIN) = 1; - BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 1; - BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 1; - BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 1; - - BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1; - BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1; - BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1; - BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1; - - wiggle_fast_pos1(); /* send start bit to card */ - crcshift=8; - while(cnt--) { - datshift=8; - do { - datshift-=4; -/* if(((*buf)>>datshift) & 0x8) { - BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1; - } else { - BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1; - } - if(((*buf)>>datshift) & 0x4) { - BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1; - } else { - BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1; - } - if(((*buf)>>datshift) & 0x2){ - BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1; - } else { - BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1; - } - if(((*buf)>>datshift) & 0x1){ - BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1; - } else { - BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1; - }*/ - SD_DAT0REG->FIOPIN0 = (*buf) >> datshift; - wiggle_fast_pos1(); - } while (datshift); - - crcshift-=2; - dat0 |= (((*buf)&0x01) | (((*buf)&0x10) >> 3)) << crcshift; - dat1 |= ((((*buf)&0x02) >> 1) | (((*buf)&0x20) >> 4)) << crcshift; - dat2 |= ((((*buf)&0x04) >> 2) | (((*buf)&0x40) >> 5)) << crcshift; - dat3 |= ((((*buf)&0x08) >> 3) | (((*buf)&0x80) >> 6)) << crcshift; - if(!crcshift) { - crc0 = crc_xmodem_update(crc0, dat0); - crc1 = crc_xmodem_update(crc1, dat1); - crc2 = crc_xmodem_update(crc2, dat2); - crc3 = crc_xmodem_update(crc3, dat3); - crcshift=8; - dat0=0; - dat1=0; - dat2=0; - dat3=0; - } - buf++; - } -// printf("crc0=%04x crc1=%04x crc2=%04x crc3=%04x ", crc0, crc1, crc2, crc3); - /* send crcs */ - datshift=16; - do { - datshift--; - if((crc0 >> datshift) & 1) { - BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1; - } else { - BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1; - } - if((crc1 >> datshift) & 1) { - BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1; - } else { - BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1; - } - if((crc2 >> datshift) & 1) { - BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1; - } else { - BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1; - } - if((crc3 >> datshift) & 1) { - BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1; - } else { - BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1; - } wiggle_fast_pos1(); - } while(datshift); - /* send end bit */ - BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1; - BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1; - BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1; - BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1; + BITBAND( SD_CMDREG->FIODIR, SD_CMDPIN ) = 0; - wiggle_fast_pos1(); + if ( rsplen ) + { + uint32_t timeout = 200000; - BITBAND(SD_DAT0REG->FIODIR, SD_DAT0PIN) = 0; - BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 0; - BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 0; - BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 0; + /* wait for response */ + while ( ( BITBAND( SD_CMDREG->FIOPIN, SD_CMDPIN ) ) && --timeout ) + { + wiggle_fast_neg1(); + } - wiggle_fast_neg(3); - dat0=0; + if ( !timeout ) + { + printf( "CMD%d timed out\n", cmdno ); + return 0; /* no response within timeout */ + } - datshift=4; - do { - datshift--; - dat0 |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) << datshift); - wiggle_fast_neg1(); - } while (datshift); - DBG_SD printf("crc %02x\n", dat0); - if((dat0 & 7) != 2) { - printf("crc error! %02x\n", dat0); - while(1); - } - if(dat0 & 8) { - printf("missing start bit in CRC status response...\n"); - } - wiggle_fast_neg(2); - wait_busy(); + i = rsplen; + uint8_t cmddata = 0, datdata = 0; + + while ( i-- ) /* process response */ + { + cmdshift = 8; + + do + { + if ( dat ) + { + if ( !( BITBAND( SD_DAT0REG->FIOPIN, SD_DAT0PIN ) ) ) + { + printf( "data start during response\n" ); + j = datcnt; + state = CMD_RSPDAT; + break; + } + } + + cmdshift--; + cmddata |= ( BITBAND( SD_CMDREG->FIOPIN, SD_CMDPIN ) ) << cmdshift; + wiggle_fast_neg1(); + } + while ( cmdshift ); + + if ( state == CMD_RSPDAT ) + { + break; + } + + *rsp = cmddata; + cmddata = 0; + rsp++; + } + + if ( state == CMD_RSPDAT ) /* process response+data */ + { + int startbit = 1; + DBG_SD printf( "processing rsp+data cmdshift=%d i=%d j=%d\n", cmdshift, i, j ); + datshift = 8; + + while ( 1 ) + { + cmdshift--; + cmddata |= ( BITBAND( SD_CMDREG->FIOPIN, SD_CMDPIN ) ) << cmdshift; + + if ( !cmdshift ) + { + cmdshift = 8; + *rsp = cmddata; + cmddata = 0; + rsp++; + i--; + + if ( !i ) + { + DBG_SD printf( "response end\n" ); + + if ( j ) + { + state = CMD_DAT; /* response over, remaining data */ + } + + break; + } + } + + if ( !startbit ) + { + datshift -= 4; + datdata |= SD_DAT << datshift; + + if ( !datshift ) + { + datshift = 8; + *buf = datdata; + datdata = 0; + buf++; + j--; + + if ( !j ) + { + break; + } + } + } + + startbit = 0; + wiggle_fast_neg1(); + } + } + + if ( dat && state != CMD_DAT ) /* response ended before data */ + { + BITBAND( SD_CMDREG->FIODIR, SD_CMDPIN ) = 1; + state = CMD_DAT; + j = datcnt; + datshift = 8; + timeout = 2000000; + DBG_SD printf( "response over, waiting for data...\n" ); + + /* wait for data start bit on DAT0 */ + while ( ( BITBAND( SD_DAT0REG->FIOPIN, SD_DAT0PIN ) ) && --timeout ) + { + wiggle_fast_neg1(); + } + + // printf("%ld\n", timeout); + if ( !timeout ) + { + printf( "timed out!\n" ); + } + + wiggle_fast_neg1(); /* eat the start bit */ + + if ( sd_offload ) + { + if ( sd_offload_partial ) + { + if ( sd_offload_partial_start != 0 ) + { + if ( during_blocktrans == TRANS_MID ) + { + sd_offload_partial_start |= 0x8000; + } + } + + if ( sd_offload_partial_end != 512 ) + { + sd_offload_partial_end |= 0x8000; + } + + DBG_SD printf( "new partial %d - %d\n", sd_offload_partial_start, sd_offload_partial_end ); + fpga_set_sddma_range( sd_offload_partial_start, sd_offload_partial_end ); + fpga_sddma( sd_offload_tgt, 1 ); + // sd_offload_partial=0; + last_offset = sd_offload_partial_end; + } + else + { + fpga_sddma( sd_offload_tgt, 0 ); + last_offset = 0; + } + + state = CMD_RSP; + return rsplen; + } + } + + if ( state == CMD_DAT ) /* transfer rest of data */ + { + DBG_SD printf( "remaining data: %d\n", j ); + + if ( datshift == 8 ) + { + while ( 1 ) + { + datdata |= SD_DAT << 4; + wiggle_fast_neg1(); + + datdata |= SD_DAT; + wiggle_fast_neg1(); + + *buf = datdata; + datdata = 0; + buf++; + j--; + + if ( !j ) + { + break; + } + } + } + else + { + + while ( 1 ) + { + datshift -= 4; + datdata |= SD_DAT << datshift; + + if ( !datshift ) + { + datshift = 8; + *buf = datdata; + datdata = 0; + buf++; + j--; + + if ( !j ) + { + break; + } + } + + wiggle_fast_neg1(); + } + } + } + + if ( dat ) + { +#ifdef CONFIG_SD_DATACRC + + if ( get_and_check_datacrc( buf - 512 ) ) + { + return CRC_ERROR; + } + +#else + /* eat the crcs */ + wiggle_fast_neg( 17 ); +#endif + } + + if ( waitbusy ) + { + DBG_SD printf( "waitbusy after send_cmd\n" ); + wait_busy(); + } + + state = CMD_RSP; + } + + rsp -= rsplen; + DBG_SD printf( "send_command_fast: CMD%d response: %02x%02x%02x%02x%02x%02x\n", cmdno, rsp[0], rsp[1], rsp[2], rsp[3], + rsp[4], rsp[5] ); + BITBAND( SD_CMDREG->FIODIR, SD_CMDPIN ) = 1; + return rsplen; } -void read_block(uint32_t address, uint8_t *buf) { - DBG_SD printf("read_block addr=%08lx last_addr=%08lx offld=%d/%d offst=%04x offed=%04x last_off=%04x\n", address, last_block, sd_offload, sd_offload_partial, sd_offload_partial_start, sd_offload_partial_end, last_offset); - if(during_blocktrans == TRANS_READ && (last_block == address-1)) { -//uart_putc('r'); -#ifdef CONFIG_SD_DATACRC - int cmd_res; - if((cmd_res = stream_datablock(buf)) == CRC_ERROR) { - while(cmd_res == CRC_ERROR) { - cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp); - cmd_res = cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp); - } - } -#else - stream_datablock(buf); -#endif - last_block = address; - last_offset = sd_offload_partial_end & 0x1ff; - if(sd_offload_partial && sd_offload_partial_end != 512) { - during_blocktrans = TRANS_MID; - } - sd_offload_partial = 0; - } else if (during_blocktrans == TRANS_MID - && last_block == address - && last_offset == sd_offload_partial_start - && sd_offload_partial) { - sd_offload_partial_start |= 0x8000; - stream_datablock(buf); - during_blocktrans = TRANS_READ; - last_offset = sd_offload_partial_end & 0x1ff; - sd_offload_partial = 0; - } else { - if(during_blocktrans) { -// uart_putc('_'); -//printf("nonseq read (%lx -> %lx), restarting transmission\n", last_block, address); - /* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */ - cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp); - } - during_blocktrans = TRANS_READ; - last_block = address; - if(!ccs) { - address <<= 9; - } -#ifdef CONFIG_SD_DATACRC - while(1) { - if(cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp) != CRC_ERROR) break; - cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp); - }; -#else - cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp); -#endif - sd_offload_partial = 0; - } -// printf("trans state = %d\n", during_blocktrans); + +static inline void make_crc7( uint8_t *cmd ) +{ + cmd[5] = crc7update( 0, cmd[0] ); + cmd[5] = crc7update( cmd[5], cmd[1] ); + cmd[5] = crc7update( cmd[5], cmd[2] ); + cmd[5] = crc7update( cmd[5], cmd[3] ); + cmd[5] = crc7update( cmd[5], cmd[4] ); + cmd[5] = ( cmd[5] << 1 ) | 1; } -void write_block(uint32_t address, uint8_t* buf) { - if(during_blocktrans == TRANS_WRITE && (last_block == address-1)) { - wait_busy(); - send_datablock(buf); - last_block=address; - } else { - if(during_blocktrans) { - /* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */ - cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp); +int cmd_slow( uint8_t cmd, uint32_t param, uint8_t crc, uint8_t *dat, uint8_t *rsp ) +{ + uint8_t cmdbuf[6]; + cmdbuf[0] = 0x40 | cmd; + cmdbuf[1] = param >> 24; + cmdbuf[2] = param >> 16; + cmdbuf[3] = param >> 8; + cmdbuf[4] = param; + + if ( !crc ) + { + make_crc7( cmdbuf ); } - wait_busy(); - last_block=address; - if(!ccs) { - address <<= 9; + else + { + cmdbuf[5] = crc; + } + + return send_command_slow( cmdbuf, rsp ); +} + +int acmd_slow( uint8_t cmd, uint32_t param, uint8_t crc, uint8_t *dat, uint8_t *rsp ) +{ + if ( !( cmd_slow( APP_CMD, rca, 0, NULL, rsp ) ) ) + { + return 0; + } + + return cmd_slow( cmd, param, crc, dat, rsp ); +} + +int cmd_fast( uint8_t cmd, uint32_t param, uint8_t crc, uint8_t *dat, uint8_t *rsp ) +{ + uint8_t cmdbuf[6]; + cmdbuf[0] = 0x40 | cmd; + cmdbuf[1] = param >> 24; + cmdbuf[2] = param >> 16; + cmdbuf[3] = param >> 8; + cmdbuf[4] = param; + + if ( !crc ) + { + make_crc7( cmdbuf ); + } + else + { + cmdbuf[5] = crc; + } + + return send_command_fast( cmdbuf, rsp, dat ); +} + +int acmd_fast( uint8_t cmd, uint32_t param, uint8_t crc, uint8_t *dat, uint8_t *rsp ) +{ + if ( !( cmd_fast( APP_CMD, rca, 0, NULL, rsp ) ) ) + { + return 0; + } + + return cmd_fast( cmd, param, crc, dat, rsp ); +} + +int stream_datablock( uint8_t *buf ) +{ + // uint8_t datshift=8; + int j = 512; + uint8_t datdata = 0; + uint32_t timeout = 1000000; + + DBG_SD printf( "stream_datablock: wait for ready...\n" ); + + if ( during_blocktrans != TRANS_MID ) + { + while ( ( BITBAND( SD_DAT0REG->FIOPIN, SD_DAT0PIN ) ) && --timeout ) + { + wiggle_fast_neg1(); + } + + DBG_SD if ( !timeout ) + { + printf( "timeout!\n" ); + } + + wiggle_fast_neg1(); /* eat the start bit */ + } + + if ( sd_offload ) + { + if ( sd_offload_partial ) + { + if ( sd_offload_partial_start != 0 ) + { + if ( during_blocktrans == TRANS_MID ) + { + sd_offload_partial_start |= 0x8000; + } + } + + if ( sd_offload_partial_end != 512 ) + { + sd_offload_partial_end |= 0x8000; + } + + DBG_SD printf( "str partial %d - %d\n", sd_offload_partial_start, sd_offload_partial_end ); + fpga_set_sddma_range( sd_offload_partial_start, sd_offload_partial_end ); + fpga_sddma( sd_offload_tgt, 1 ); + } + else + { + fpga_sddma( sd_offload_tgt, 0 ); + } + } + else + { + while ( 1 ) + { + datdata = SD_DAT << 4; + wiggle_fast_neg1(); + + datdata |= SD_DAT; + wiggle_fast_neg1(); + + *buf = datdata; + buf++; + j--; + + if ( !j ) + { + break; + } + } + +#ifdef CONFIG_SD_DATACRC + return get_and_check_datacrc( buf - 512 ); +#else + /* eat the crcs */ + wiggle_fast_neg( 17 ); +#endif + } + + return 0; +} + +void send_datablock( uint8_t *buf ) +{ + uint16_t crc0 = 0, crc1 = 0, crc2 = 0, crc3 = 0, cnt = 512; + uint8_t dat0 = 0, dat1 = 0, dat2 = 0, dat3 = 0, crcshift, datshift; + + wiggle_fast_pos1(); + BITBAND( SD_DAT0REG->FIODIR, SD_DAT0PIN ) = 1; + BITBAND( SD_DAT1REG->FIODIR, SD_DAT1PIN ) = 1; + BITBAND( SD_DAT2REG->FIODIR, SD_DAT2PIN ) = 1; + BITBAND( SD_DAT3REG->FIODIR, SD_DAT3PIN ) = 1; + + BITBAND( SD_DAT0REG->FIOCLR, SD_DAT0PIN ) = 1; + BITBAND( SD_DAT1REG->FIOCLR, SD_DAT1PIN ) = 1; + BITBAND( SD_DAT2REG->FIOCLR, SD_DAT2PIN ) = 1; + BITBAND( SD_DAT3REG->FIOCLR, SD_DAT3PIN ) = 1; + + wiggle_fast_pos1(); /* send start bit to card */ + crcshift = 8; + + while ( cnt-- ) + { + datshift = 8; + + do + { + datshift -= 4; + /* if(((*buf)>>datshift) & 0x8) { + BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1; + } else { + BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1; + } + if(((*buf)>>datshift) & 0x4) { + BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1; + } else { + BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1; + } + if(((*buf)>>datshift) & 0x2){ + BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1; + } else { + BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1; + } + if(((*buf)>>datshift) & 0x1){ + BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1; + } else { + BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1; + }*/ + SD_DAT0REG->FIOPIN0 = ( *buf ) >> datshift; + wiggle_fast_pos1(); + } + while ( datshift ); + + crcshift -= 2; + dat0 |= ( ( ( *buf ) & 0x01 ) | ( ( ( *buf ) & 0x10 ) >> 3 ) ) << crcshift; + dat1 |= ( ( ( ( *buf ) & 0x02 ) >> 1 ) | ( ( ( *buf ) & 0x20 ) >> 4 ) ) << crcshift; + dat2 |= ( ( ( ( *buf ) & 0x04 ) >> 2 ) | ( ( ( *buf ) & 0x40 ) >> 5 ) ) << crcshift; + dat3 |= ( ( ( ( *buf ) & 0x08 ) >> 3 ) | ( ( ( *buf ) & 0x80 ) >> 6 ) ) << crcshift; + + if ( !crcshift ) + { + crc0 = crc_xmodem_update( crc0, dat0 ); + crc1 = crc_xmodem_update( crc1, dat1 ); + crc2 = crc_xmodem_update( crc2, dat2 ); + crc3 = crc_xmodem_update( crc3, dat3 ); + crcshift = 8; + dat0 = 0; + dat1 = 0; + dat2 = 0; + dat3 = 0; + } + + buf++; + } + + // printf("crc0=%04x crc1=%04x crc2=%04x crc3=%04x ", crc0, crc1, crc2, crc3); + /* send crcs */ + datshift = 16; + + do + { + datshift--; + + if ( ( crc0 >> datshift ) & 1 ) + { + BITBAND( SD_DAT0REG->FIOSET, SD_DAT0PIN ) = 1; + } + else + { + BITBAND( SD_DAT0REG->FIOCLR, SD_DAT0PIN ) = 1; + } + + if ( ( crc1 >> datshift ) & 1 ) + { + BITBAND( SD_DAT1REG->FIOSET, SD_DAT1PIN ) = 1; + } + else + { + BITBAND( SD_DAT1REG->FIOCLR, SD_DAT1PIN ) = 1; + } + + if ( ( crc2 >> datshift ) & 1 ) + { + BITBAND( SD_DAT2REG->FIOSET, SD_DAT2PIN ) = 1; + } + else + { + BITBAND( SD_DAT2REG->FIOCLR, SD_DAT2PIN ) = 1; + } + + if ( ( crc3 >> datshift ) & 1 ) + { + BITBAND( SD_DAT3REG->FIOSET, SD_DAT3PIN ) = 1; + } + else + { + BITBAND( SD_DAT3REG->FIOCLR, SD_DAT3PIN ) = 1; + } + + wiggle_fast_pos1(); + } + while ( datshift ); + + /* send end bit */ + BITBAND( SD_DAT0REG->FIOSET, SD_DAT0PIN ) = 1; + BITBAND( SD_DAT1REG->FIOSET, SD_DAT1PIN ) = 1; + BITBAND( SD_DAT2REG->FIOSET, SD_DAT2PIN ) = 1; + BITBAND( SD_DAT3REG->FIOSET, SD_DAT3PIN ) = 1; + + wiggle_fast_pos1(); + + BITBAND( SD_DAT0REG->FIODIR, SD_DAT0PIN ) = 0; + BITBAND( SD_DAT1REG->FIODIR, SD_DAT1PIN ) = 0; + BITBAND( SD_DAT2REG->FIODIR, SD_DAT2PIN ) = 0; + BITBAND( SD_DAT3REG->FIODIR, SD_DAT3PIN ) = 0; + + wiggle_fast_neg( 3 ); + dat0 = 0; + + datshift = 4; + + do + { + datshift--; + dat0 |= ( ( BITBAND( SD_DAT0REG->FIOPIN, SD_DAT0PIN ) ) << datshift ); + wiggle_fast_neg1(); + } + while ( datshift ); + + DBG_SD printf( "crc %02x\n", dat0 ); + + if ( ( dat0 & 7 ) != 2 ) + { + printf( "crc error! %02x\n", dat0 ); + + while ( 1 ); + } + + if ( dat0 & 8 ) + { + printf( "missing start bit in CRC status response...\n" ); + } + + wiggle_fast_neg( 2 ); + wait_busy(); +} + +void read_block( uint32_t address, uint8_t *buf ) +{ + DBG_SD printf( "read_block addr=%08lx last_addr=%08lx offld=%d/%d offst=%04x offed=%04x last_off=%04x\n", address, + last_block, sd_offload, sd_offload_partial, sd_offload_partial_start, sd_offload_partial_end, last_offset ); + + if ( during_blocktrans == TRANS_READ && ( last_block == address - 1 ) ) + { + //uart_putc('r'); +#ifdef CONFIG_SD_DATACRC + int cmd_res; + + if ( ( cmd_res = stream_datablock( buf ) ) == CRC_ERROR ) + { + while ( cmd_res == CRC_ERROR ) + { + cmd_fast( STOP_TRANSMISSION, 0, 0x61, NULL, rsp ); + cmd_res = cmd_fast( READ_MULTIPLE_BLOCK, address, 0, buf, rsp ); + } + } + +#else + stream_datablock( buf ); +#endif + last_block = address; + last_offset = sd_offload_partial_end & 0x1ff; + + if ( sd_offload_partial && sd_offload_partial_end != 512 ) + { + during_blocktrans = TRANS_MID; + } + + sd_offload_partial = 0; + } + else if ( during_blocktrans == TRANS_MID + && last_block == address + && last_offset == sd_offload_partial_start + && sd_offload_partial ) + { + sd_offload_partial_start |= 0x8000; + stream_datablock( buf ); + during_blocktrans = TRANS_READ; + last_offset = sd_offload_partial_end & 0x1ff; + sd_offload_partial = 0; + } + else + { + if ( during_blocktrans ) + { + // uart_putc('_'); + //printf("nonseq read (%lx -> %lx), restarting transmission\n", last_block, address); + /* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */ + cmd_fast( STOP_TRANSMISSION, 0, 0x61, NULL, rsp ); + } + + during_blocktrans = TRANS_READ; + last_block = address; + + if ( !ccs ) + { + address <<= 9; + } + +#ifdef CONFIG_SD_DATACRC + + while ( 1 ) + { + if ( cmd_fast( READ_MULTIPLE_BLOCK, address, 0, buf, rsp ) != CRC_ERROR ) + { + break; + } + + cmd_fast( STOP_TRANSMISSION, 0, 0x61, NULL, rsp ); + }; + +#else + cmd_fast( READ_MULTIPLE_BLOCK, address, 0, buf, rsp ); + +#endif + sd_offload_partial = 0; + } + + // printf("trans state = %d\n", during_blocktrans); +} + +void write_block( uint32_t address, uint8_t *buf ) +{ + if ( during_blocktrans == TRANS_WRITE && ( last_block == address - 1 ) ) + { + wait_busy(); + send_datablock( buf ); + last_block = address; + } + else + { + if ( during_blocktrans ) + { + /* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */ + cmd_fast( STOP_TRANSMISSION, 0, 0x61, NULL, rsp ); + } + + wait_busy(); + last_block = address; + + if ( !ccs ) + { + address <<= 9; + } + + /* only send cmd & get response */ + cmd_fast( WRITE_MULTIPLE_BLOCK, address, 0, NULL, rsp ); + DBG_SD printf( "write_block: CMD25 response = %02x%02x%02x%02x%02x%02x\n", rsp[0], rsp[1], rsp[2], rsp[3], rsp[4], + rsp[5] ); + wiggle_fast_pos( 8 ); + send_datablock( buf ); + during_blocktrans = TRANS_WRITE; } - /* only send cmd & get response */ - cmd_fast(WRITE_MULTIPLE_BLOCK, address, 0, NULL, rsp); - DBG_SD printf("write_block: CMD25 response = %02x%02x%02x%02x%02x%02x\n", rsp[0], rsp[1], rsp[2], rsp[3], rsp[4], rsp[5]); - wiggle_fast_pos(8); - send_datablock(buf); - during_blocktrans = TRANS_WRITE; - } } /* send STOP_TRANSMISSION after multiple block write * and reset during_blocktrans status */ -void flush_write(void) { - cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp); - wait_busy(); - during_blocktrans = TRANS_NONE; +void flush_write( void ) +{ + cmd_fast( STOP_TRANSMISSION, 0, 0x61, NULL, rsp ); + wait_busy(); + during_blocktrans = TRANS_NONE; } // // Public functions // -DRESULT sdn_ioctl(BYTE drv, BYTE cmd, void *buffer) { - DRESULT res; - if(drv >= MAX_CARDS) { - res = STA_NOINIT|STA_NODISK; - } else { - switch(cmd) { - case CTRL_SYNC: - flush_write(); - res = RES_OK; - break; +DRESULT sdn_ioctl( BYTE drv, BYTE cmd, void *buffer ) +{ + DRESULT res; - default: - res = RES_PARERR; + if ( drv >= MAX_CARDS ) + { + res = STA_NOINIT | STA_NODISK; } - } - return res; -} -DRESULT disk_ioctl(BYTE drv, BYTE cmd, void *buffer) __attribute__ ((weak, alias("sdn_ioctl"))); + else + { + switch ( cmd ) + { + case CTRL_SYNC: + flush_write(); + res = RES_OK; + break; -DRESULT sdn_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count) { - uint8_t sec; - if(drv >= MAX_CARDS) { - return RES_PARERR; - } - readled(1); - for(sec=0; sec=MAX_CARDS) { - return STA_NOINIT|STA_NODISK; - } - - if(sdn_status(drv) & STA_NODISK) { - return STA_NOINIT|STA_NODISK; - } - /* if the card is sending data from before a reset we try to deselect it - prior to initialization */ - for(rsplen=0; rsplen<2042; rsplen++) { - if(!(BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN))) { - printf("card seems to be sending data, attempting deselect\n"); - cmd_slow(SELECT_CARD, 0, 0, NULL, rsp); + default: + res = RES_PARERR; + } } - wiggle_slow_neg(1); - } - printf("sd_init start\n"); - BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 1; - BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1; - cmd_slow(GO_IDLE_STATE, 0, 0x95, NULL, rsp); - if((rsplen=cmd_slow(SEND_IF_COND, 0x000001aa, 0x87, NULL, rsp))) { - DBG_SD printf("CMD8 response:\n"); - DBG_SD uart_trace(rsp, 0, rsplen, 0); - hcs=1; - } - while(1) { - if(!(acmd_slow(SD_SEND_OP_COND, (hcs << 30) | 0xfc0000, 0, NULL, rsp))) { - printf("ACMD41 no response!\n"); + return res; +} +DRESULT disk_ioctl( BYTE drv, BYTE cmd, void *buffer ) __attribute__ ( ( weak, alias( "sdn_ioctl" ) ) ); + +DRESULT sdn_read( BYTE drv, BYTE *buffer, DWORD sector, BYTE count ) +{ + uint8_t sec; + + if ( drv >= MAX_CARDS ) + { + return RES_PARERR; } - if(rsp[1]&0x80) break; - } - BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 0; - BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1; + readled( 1 ); - ccs = (rsp[1]>>6) & 1; /* SDHC/XC */ - - cmd_slow(ALL_SEND_CID, 0, 0x4d, NULL, rsp); - if(cmd_slow(SEND_RELATIVE_ADDR, 0, 0x21, NULL, rsp)) { - rca=(rsp[1]<<24) | (rsp[2]<<16); - printf("RCA: %04lx\n", rca>>16); - } else { - printf("CMD3 no response!\n"); - rca=0; - } - - /* record CSD for getinfo */ - cmd_slow(SEND_CSD, rca, 0, NULL, csd); - sdn_getinfo(drv, 0, &di); - - /* record CID */ - cmd_slow(SEND_CID, rca, 0, NULL, cid); - - /* select the card */ - if(cmd_slow(SELECT_CARD, rca, 0, NULL, rsp)) { - printf("card selected!\n"); - } else { - printf("CMD7 no response!\n"); - } - - /* get card status */ - cmd_slow(SEND_STATUS, rca, 0, NULL, rsp); - - /* set bus width */ - acmd_slow(SD_SET_BUS_WIDTH, 0x2, 0, NULL, rsp); - - /* set block length */ - cmd_slow(SET_BLOCKLEN, 0x200, 0, NULL, rsp); - - printf("SD init complete. SDHC/XC=%d\n", ccs); - disk_state = DISK_OK; - during_blocktrans = TRANS_NONE; - return sdn_status(drv); -} - -DSTATUS disk_initialize(BYTE drv) __attribute__ ((weak, alias("sdn_initialize"))); - -void sdn_init(void) { - /* enable GPIO interrupt on SD detect pin, both edges */ -/* NVIC_EnableIRQ(EINT3_IRQn); - SD_DT_INT_SETUP(); */ - /* disconnect SSP1 */ - LPC_PINCON->PINSEL0 &= ~(BV(13) | BV(15) | BV(17) | BV(19)); - /* prepare GPIOs */ - BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 0; - BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 0; - BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 0; - BITBAND(SD_DAT0REG->FIODIR, SD_DAT0PIN) = 0; - BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 1; - BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1; - BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN) = 1; - LPC_PINCON->PINMODE0 &= ~(BV(14) | BV(15)); - LPC_GPIO2->FIOPIN0 = 0x00; - LPC_GPIO2->FIOMASK0 = ~0xf; -} -void disk_init(void) __attribute__ ((weak, alias("sdn_init"))); - - -DSTATUS sdn_status(BYTE drv) { - if (SDCARD_DETECT) { - if (SDCARD_WP) { - return STA_PROTECT; - } else { - return RES_OK; + for ( sec = 0; sec < count; sec++ ) + { + read_block( sector + sec, buffer ); + buffer += 512; } - } else { - return STA_NOINIT|STA_NODISK; - } + + readled( 0 ); + return RES_OK; } -DSTATUS disk_status(BYTE drv) __attribute__ ((weak, alias("sdn_status"))); +DRESULT disk_read( BYTE drv, BYTE *buffer, DWORD sector, BYTE count ) __attribute__ ( ( weak, alias( "sdn_read" ) ) ); -DRESULT sdn_getinfo(BYTE drv, BYTE page, void *buffer) { - uint32_t capacity; +DSTATUS sdn_initialize( BYTE drv ) +{ - if (drv >= MAX_CARDS) { - return RES_NOTRDY; - } - if (sdn_status(drv) & STA_NODISK) { - return RES_NOTRDY; - } - if (page != 0) { - return RES_ERROR; - } - if (ccs) { - /* Special CSD for SDHC cards */ - capacity = (1 + getbits(csd,127-69+8,22)) * 1024; - } else { - /* Assume that MMC-CSD 1.0/1.1/1.2 and SD-CSD 1.1 are the same... */ - uint8_t exponent = 2 + getbits(csd, 127-49+8, 3); - capacity = 1 + getbits(csd, 127-73+8, 12); - exponent += getbits(csd, 127-83+8,4) - 9; - while (exponent--) capacity *= 2; - } + uint8_t rsp[17]; /* space for response */ + int rsplen; + uint8_t hcs = 0; + rca = 0; - diskinfo0_t *di = buffer; - di->validbytes = sizeof(diskinfo0_t); - di->disktype = DISK_TYPE_SD; - di->sectorsize = 2; - di->sectorcount = capacity; + if ( drv >= MAX_CARDS ) + { + return STA_NOINIT | STA_NODISK; + } - printf("card capacity: %lu sectors\n", capacity); - return RES_OK; -} -DRESULT disk_getinfo(BYTE drv, BYTE page, void *buffer) __attribute__ ((weak, alias("sdn_getinfo"))); + if ( sdn_status( drv ) & STA_NODISK ) + { + return STA_NOINIT | STA_NODISK; + } -DRESULT sdn_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) { - uint8_t sec; - uint8_t *buf = (uint8_t*)buffer; - if(drv >= MAX_CARDS) { - return RES_NOTRDY; - } - if (sdn_status(drv) & STA_NODISK) { - return RES_NOTRDY; - } - writeled(1); - for(sec=0; secFIOPIN, SD_DAT3PIN ) ) ) + { + printf( "card seems to be sending data, attempting deselect\n" ); + cmd_slow( SELECT_CARD, 0, 0, NULL, rsp ); + } + + wiggle_slow_neg( 1 ); + } + + printf( "sd_init start\n" ); + BITBAND( SD_DAT3REG->FIODIR, SD_DAT3PIN ) = 1; + BITBAND( SD_DAT3REG->FIOSET, SD_DAT3PIN ) = 1; + cmd_slow( GO_IDLE_STATE, 0, 0x95, NULL, rsp ); + + if ( ( rsplen = cmd_slow( SEND_IF_COND, 0x000001aa, 0x87, NULL, rsp ) ) ) + { + DBG_SD printf( "CMD8 response:\n" ); + DBG_SD uart_trace( rsp, 0, rsplen, 0 ); + hcs = 1; + } + + while ( 1 ) + { + if ( !( acmd_slow( SD_SEND_OP_COND, ( hcs << 30 ) | 0xfc0000, 0, NULL, rsp ) ) ) + { + printf( "ACMD41 no response!\n" ); + } + + if ( rsp[1] & 0x80 ) + { + break; + } + } + + BITBAND( SD_DAT3REG->FIODIR, SD_DAT3PIN ) = 0; + BITBAND( SD_DAT3REG->FIOCLR, SD_DAT3PIN ) = 1; + + ccs = ( rsp[1] >> 6 ) & 1; /* SDHC/XC */ + + cmd_slow( ALL_SEND_CID, 0, 0x4d, NULL, rsp ); + + if ( cmd_slow( SEND_RELATIVE_ADDR, 0, 0x21, NULL, rsp ) ) + { + rca = ( rsp[1] << 24 ) | ( rsp[2] << 16 ); + printf( "RCA: %04lx\n", rca >> 16 ); + } + else + { + printf( "CMD3 no response!\n" ); + rca = 0; + } + + /* record CSD for getinfo */ + cmd_slow( SEND_CSD, rca, 0, NULL, csd ); + sdn_getinfo( drv, 0, &di ); + + /* record CID */ + cmd_slow( SEND_CID, rca, 0, NULL, cid ); + + /* select the card */ + if ( cmd_slow( SELECT_CARD, rca, 0, NULL, rsp ) ) + { + printf( "card selected!\n" ); + } + else + { + printf( "CMD7 no response!\n" ); + } + + /* get card status */ + cmd_slow( SEND_STATUS, rca, 0, NULL, rsp ); + + /* set bus width */ + acmd_slow( SD_SET_BUS_WIDTH, 0x2, 0, NULL, rsp ); + + /* set block length */ + cmd_slow( SET_BLOCKLEN, 0x200, 0, NULL, rsp ); + + printf( "SD init complete. SDHC/XC=%d\n", ccs ); + disk_state = DISK_OK; + during_blocktrans = TRANS_NONE; + return sdn_status( drv ); } -DRESULT disk_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) __attribute__ ((weak, alias("sdn_write"))); +DSTATUS disk_initialize( BYTE drv ) __attribute__ ( ( weak, alias( "sdn_initialize" ) ) ); + +void sdn_init( void ) +{ + /* enable GPIO interrupt on SD detect pin, both edges */ + /* NVIC_EnableIRQ(EINT3_IRQn); + SD_DT_INT_SETUP(); */ + /* disconnect SSP1 */ + LPC_PINCON->PINSEL0 &= ~( BV( 13 ) | BV( 15 ) | BV( 17 ) | BV( 19 ) ); + /* prepare GPIOs */ + BITBAND( SD_DAT3REG->FIODIR, SD_DAT3PIN ) = 0; + BITBAND( SD_DAT2REG->FIODIR, SD_DAT2PIN ) = 0; + BITBAND( SD_DAT1REG->FIODIR, SD_DAT1PIN ) = 0; + BITBAND( SD_DAT0REG->FIODIR, SD_DAT0PIN ) = 0; + BITBAND( SD_CLKREG->FIODIR, SD_CLKPIN ) = 1; + BITBAND( SD_CMDREG->FIODIR, SD_CMDPIN ) = 1; + BITBAND( SD_CMDREG->FIOPIN, SD_CMDPIN ) = 1; + LPC_PINCON->PINMODE0 &= ~( BV( 14 ) | BV( 15 ) ); + LPC_GPIO2->FIOPIN0 = 0x00; + LPC_GPIO2->FIOMASK0 = ~0xf; +} +void disk_init( void ) __attribute__ ( ( weak, alias( "sdn_init" ) ) ); + + +DSTATUS sdn_status( BYTE drv ) +{ + if ( SDCARD_DETECT ) + { + if ( SDCARD_WP ) + { + return STA_PROTECT; + } + else + { + return RES_OK; + } + } + else + { + return STA_NOINIT | STA_NODISK; + } +} +DSTATUS disk_status( BYTE drv ) __attribute__ ( ( weak, alias( "sdn_status" ) ) ); + +DRESULT sdn_getinfo( BYTE drv, BYTE page, void *buffer ) +{ + uint32_t capacity; + + if ( drv >= MAX_CARDS ) + { + return RES_NOTRDY; + } + + if ( sdn_status( drv ) & STA_NODISK ) + { + return RES_NOTRDY; + } + + if ( page != 0 ) + { + return RES_ERROR; + } + + if ( ccs ) + { + /* Special CSD for SDHC cards */ + capacity = ( 1 + getbits( csd, 127 - 69 + 8, 22 ) ) * 1024; + } + else + { + /* Assume that MMC-CSD 1.0/1.1/1.2 and SD-CSD 1.1 are the same... */ + uint8_t exponent = 2 + getbits( csd, 127 - 49 + 8, 3 ); + capacity = 1 + getbits( csd, 127 - 73 + 8, 12 ); + exponent += getbits( csd, 127 - 83 + 8, 4 ) - 9; + + while ( exponent-- ) + { + capacity *= 2; + } + } + + diskinfo0_t *di = buffer; + di->validbytes = sizeof( diskinfo0_t ); + di->disktype = DISK_TYPE_SD; + di->sectorsize = 2; + di->sectorcount = capacity; + + printf( "card capacity: %lu sectors\n", capacity ); + return RES_OK; +} +DRESULT disk_getinfo( BYTE drv, BYTE page, void *buffer ) __attribute__ ( ( weak, alias( "sdn_getinfo" ) ) ); + +DRESULT sdn_write( BYTE drv, const BYTE *buffer, DWORD sector, BYTE count ) +{ + uint8_t sec; + uint8_t *buf = ( uint8_t * )buffer; + + if ( drv >= MAX_CARDS ) + { + return RES_NOTRDY; + } + + if ( sdn_status( drv ) & STA_NODISK ) + { + return RES_NOTRDY; + } + + writeled( 1 ); + + for ( sec = 0; sec < count; sec++ ) + { + write_block( sector + sec, buf ); + buf += 512; + } + + writeled( 0 ); + return RES_OK; +} + +DRESULT disk_write( BYTE drv, const BYTE *buffer, DWORD sector, BYTE count ) __attribute__ ( ( weak, + alias( "sdn_write" ) ) ); /* Detect changes of SD card 0 */ -void sdn_changed() { - if (sd_changed) { - printf("ch "); - if(SDCARD_DETECT) { - disk_state = DISK_CHANGED; - } else { - disk_state = DISK_REMOVED; +void sdn_changed() +{ + if ( sd_changed ) + { + printf( "ch " ); + + if ( SDCARD_DETECT ) + { + disk_state = DISK_CHANGED; + } + else + { + disk_state = DISK_REMOVED; + } + + sd_changed = 0; } - sd_changed = 0; - } } /* measure sd access time */ -void sdn_gettacc(uint32_t *tacc_max, uint32_t *tacc_avg) { - uint32_t sec1 = 0; - uint32_t sec2 = 0; - uint32_t time, time_max = 0; - uint32_t time_avg = 0LL; - uint32_t numread = 16384; - int i; - int sec_step = di.sectorcount / numread - 1; - if(disk_state == DISK_REMOVED) return; - sdn_checkinit(0); - for (i=0; i < 128; i++) { - sd_offload_tgt=2; - sd_offload=1; - sdn_read(0, NULL, 0, 1); - sd_offload_tgt=2; - sd_offload=1; - sdn_read(0, NULL, i*sec_step, 1); - } - for (i=0; i < numread && sram_readbyte(SRAM_CMD_ADDR) != 0x00 && disk_state != DISK_REMOVED; i++) { - /* reset timer */ - LPC_RIT->RICTRL = 0; - sd_offload_tgt=2; - sd_offload=1; - sdn_read(0, NULL, sec1, 2); - sec1 += 2; - /* start timer */ - LPC_RIT->RICOUNTER = 0; - LPC_RIT->RICTRL = BV(RITEN); - sd_offload_tgt=2; - sd_offload=1; - sdn_read(0, NULL, sec2, 1); - /* read timer */ - time = LPC_RIT->RICOUNTER; -/* sd_offload_tgt=2; - sd_offload=1; - sdn_read(0, NULL, sec2, 15);*/ - time_avg += time/16; - if(time > time_max) { - time_max = time; +void sdn_gettacc( uint32_t *tacc_max, uint32_t *tacc_avg ) +{ + uint32_t sec1 = 0; + uint32_t sec2 = 0; + uint32_t time, time_max = 0; + uint32_t time_avg = 0LL; + uint32_t numread = 16384; + int i; + int sec_step = di.sectorcount / numread - 1; + + if ( disk_state == DISK_REMOVED ) + { + return; + } + + sdn_checkinit( 0 ); + + for ( i = 0; i < 128; i++ ) + { + sd_offload_tgt = 2; + sd_offload = 1; + sdn_read( 0, NULL, 0, 1 ); + sd_offload_tgt = 2; + sd_offload = 1; + sdn_read( 0, NULL, i * sec_step, 1 ); + } + + for ( i = 0; i < numread && sram_readbyte( SRAM_CMD_ADDR ) != 0x00 && disk_state != DISK_REMOVED; i++ ) + { + /* reset timer */ + LPC_RIT->RICTRL = 0; + sd_offload_tgt = 2; + sd_offload = 1; + sdn_read( 0, NULL, sec1, 2 ); + sec1 += 2; + /* start timer */ + LPC_RIT->RICOUNTER = 0; + LPC_RIT->RICTRL = BV( RITEN ); + sd_offload_tgt = 2; + sd_offload = 1; + sdn_read( 0, NULL, sec2, 1 ); + /* read timer */ + time = LPC_RIT->RICOUNTER; + /* sd_offload_tgt=2; + sd_offload=1; + sdn_read(0, NULL, sec2, 15);*/ + time_avg += time / 16; + + if ( time > time_max ) + { + time_max = time; + } + + sec2 += sec_step; + } + + time_avg = time_avg / ( i + 1 ) * 16; + sd_offload = 0; + LPC_RIT->RICTRL = 0; + + if ( disk_state != DISK_REMOVED ) + { + *tacc_max = time_max / ( CONFIG_CPU_FREQUENCY / 1000000 ) - 114; + *tacc_avg = time_avg / ( CONFIG_CPU_FREQUENCY / 1000000 ) - 114; } - sec2 += sec_step; - } - time_avg = time_avg / (i+1) * 16; - sd_offload=0; - LPC_RIT->RICTRL = 0; - if(disk_state != DISK_REMOVED) { - *tacc_max = time_max/(CONFIG_CPU_FREQUENCY / 1000000)-114; - *tacc_avg = time_avg/(CONFIG_CPU_FREQUENCY / 1000000)-114; - } } diff --git a/src/sdnative.h b/src/sdnative.h index c8cfae1..99ad013 100644 --- a/src/sdnative.h +++ b/src/sdnative.h @@ -16,16 +16,16 @@ extern int sd_offload; /* These functions are weak-aliased to disk_... */ -void sdn_init(void); -DSTATUS sdn_status(BYTE drv); -DSTATUS sdn_initialize(BYTE drv); -DRESULT sdn_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count); -DRESULT sdn_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count); -DRESULT sdn_getinfo(BYTE drv, BYTE page, void *buffer); -DRESULT sdn_ioctl(BYTE drv, BYTE cmd, void *buffer); +void sdn_init( void ); +DSTATUS sdn_status( BYTE drv ); +DSTATUS sdn_initialize( BYTE drv ); +DRESULT sdn_read( BYTE drv, BYTE *buffer, DWORD sector, BYTE count ); +DRESULT sdn_write( BYTE drv, const BYTE *buffer, DWORD sector, BYTE count ); +DRESULT sdn_getinfo( BYTE drv, BYTE page, void *buffer ); +DRESULT sdn_ioctl( BYTE drv, BYTE cmd, void *buffer ); -void sdn_changed(void); -uint8_t* sdn_getcid(void); -void sdn_gettacc(uint32_t *tacc_max, uint32_t *tacc_avg); +void sdn_changed( void ); +uint8_t *sdn_getcid( void ); +void sdn_gettacc( uint32_t *tacc_max, uint32_t *tacc_avg ); #endif diff --git a/src/smc.c b/src/smc.c index f9e3056..866874c 100644 --- a/src/smc.c +++ b/src/smc.c @@ -35,219 +35,333 @@ snes_romprops_t romprops; uint32_t hdr_addr[6] = {0xffb0, 0x101b0, 0x7fb0, 0x81b0, 0x40ffb0, 0x4101b0}; -uint8_t isFixed(uint8_t* data, int size, uint8_t value) { - uint8_t res = 1; - do { - size--; - if(data[size] != value) { - res = 0; - } - } while (size); - return res; -} +uint8_t isFixed( uint8_t *data, int size, uint8_t value ) +{ + uint8_t res = 1; -uint8_t checkChksum(uint16_t cchk, uint16_t chk) { - uint32_t sum = cchk + chk; - uint8_t res = 0; - if(sum==0x0000ffff) { - res = 1; - } - return res; -} + do + { + size--; -void smc_id(snes_romprops_t* props) { - uint8_t score, maxscore=1, score_idx=2; /* assume LoROM */ - snes_header_t* header = &(props->header); - - props->has_dspx = 0; - props->has_st0010 = 0; - props->has_cx4 = 0; - props->fpga_features = 0; - props->fpga_conf = NULL; - for(uint8_t num = 0; num < 6; num++) { - score = smc_headerscore(hdr_addr[num], header); - printf("%d: offset = %lX; score = %d\n", num, hdr_addr[num], score); // */ - if(score>=maxscore) { - score_idx=num; - maxscore=score; - } - } - if(score_idx & 1) { - props->offset = 0x200; - } else { - props->offset = 0; - } - - /* restore the chosen one */ -/*dprintf("winner is %d\n", score_idx); */ - file_readblock(header, hdr_addr[score_idx], sizeof(snes_header_t)); - - if(header->name[0x13] == 0x00 || header->name[0x13] == 0xff) { - if(header->name[0x14] == 0x00) { - const uint8_t n15 = header->map; - if(n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c - || n15 == 0xbc || n15 == 0xfc) { - if(header->licensee == 0x33 || header->licensee == 0xff) { - props->mapper_id = 0; -/*XXX do this properly */ - props->ramsize_bytes = 0x8000; - props->romsize_bytes = 0x100000; - props->expramsize_bytes = 0; - props->mapper_id = 3; /* BS-X Memory Map */ - props->region = 0; /* BS-X only existed in Japan */ - return; + if ( data[size] != value ) + { + res = 0; } - } } - } - switch(header->map & 0xef) { + while ( size ); + + return res; +} + +uint8_t checkChksum( uint16_t cchk, uint16_t chk ) +{ + uint32_t sum = cchk + chk; + uint8_t res = 0; + + if ( sum == 0x0000ffff ) + { + res = 1; + } + + return res; +} + +void smc_id( snes_romprops_t *props ) +{ + uint8_t score, maxscore = 1, score_idx = 2; /* assume LoROM */ + snes_header_t *header = &( props->header ); + + props->has_dspx = 0; + props->has_st0010 = 0; + props->has_cx4 = 0; + props->fpga_features = 0; + props->fpga_conf = NULL; + + for ( uint8_t num = 0; num < 6; num++ ) + { + score = smc_headerscore( hdr_addr[num], header ); + printf( "%d: offset = %lX; score = %d\n", num, hdr_addr[num], score ); // */ + + if ( score >= maxscore ) + { + score_idx = num; + maxscore = score; + } + } + + if ( score_idx & 1 ) + { + props->offset = 0x200; + } + else + { + props->offset = 0; + } + + /* restore the chosen one */ + /*dprintf("winner is %d\n", score_idx); */ + file_readblock( header, hdr_addr[score_idx], sizeof( snes_header_t ) ); + + if ( header->name[0x13] == 0x00 || header->name[0x13] == 0xff ) + { + if ( header->name[0x14] == 0x00 ) + { + const uint8_t n15 = header->map; + + if ( n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c + || n15 == 0xbc || n15 == 0xfc ) + { + if ( header->licensee == 0x33 || header->licensee == 0xff ) + { + props->mapper_id = 0; + /*XXX do this properly */ + props->ramsize_bytes = 0x8000; + props->romsize_bytes = 0x100000; + props->expramsize_bytes = 0; + props->mapper_id = 3; /* BS-X Memory Map */ + props->region = 0; /* BS-X only existed in Japan */ + return; + } + } + } + } + + switch ( header->map & 0xef ) + { case 0x21: /* HiROM */ - props->mapper_id = 0; - if(header->map == 0x31 && (header->carttype == 0x03 || header->carttype == 0x05)) { - props->has_dspx = 1; - props->dsp_fw = DSPFW_1B; - props->fpga_features |= FEAT_DSPX; - } - break; + props->mapper_id = 0; + + if ( header->map == 0x31 && ( header->carttype == 0x03 || header->carttype == 0x05 ) ) + { + props->has_dspx = 1; + props->dsp_fw = DSPFW_1B; + props->fpga_features |= FEAT_DSPX; + } + + break; case 0x20: /* LoROM */ - props->mapper_id = 1; - if (header->map == 0x20 && header->carttype == 0xf3) { - props->has_cx4 = 1; - props->dsp_fw = CX4FW; - props->fpga_conf = FPGA_CX4; - props->fpga_features |= FEAT_CX4; - } - else if ((header->map == 0x20 && header->carttype == 0x03) || - (header->map == 0x30 && header->carttype == 0x05 && header->licensee != 0xb2)) { - props->has_dspx = 1; - props->fpga_features |= FEAT_DSPX; - /* Pilotwings uses DSP1 instead of DSP1B */ - if(!memcmp(header->name, "PILOTWINGS", 10)) { - props->dsp_fw = DSPFW_1; - } else { - props->dsp_fw = DSPFW_1B; + props->mapper_id = 1; + + if ( header->map == 0x20 && header->carttype == 0xf3 ) + { + props->has_cx4 = 1; + props->dsp_fw = CX4FW; + props->fpga_conf = FPGA_CX4; + props->fpga_features |= FEAT_CX4; } - } else if (header->map == 0x20 && header->carttype == 0x05) { - props->has_dspx = 1; - props->dsp_fw = DSPFW_2; - props->fpga_features |= FEAT_DSPX; - } else if (header->map == 0x30 && header->carttype == 0x05 && header->licensee == 0xb2) { - props->has_dspx = 1; - props->dsp_fw = DSPFW_3; - props->fpga_features |= FEAT_DSPX; - } else if (header->map == 0x30 && header->carttype == 0x03) { - props->has_dspx = 1; - props->dsp_fw = DSPFW_4; - props->fpga_features |= FEAT_DSPX; - } else if (header->map == 0x30 && header->carttype == 0xf6 && header->romsize >= 0xa) { - props->has_dspx = 1; - props->has_st0010 = 1; - props->dsp_fw = DSPFW_ST0010; - props->fpga_features |= FEAT_ST0010; - header->ramsize = 2; - } - break; + else if ( ( header->map == 0x20 && header->carttype == 0x03 ) || + ( header->map == 0x30 && header->carttype == 0x05 && header->licensee != 0xb2 ) ) + { + props->has_dspx = 1; + props->fpga_features |= FEAT_DSPX; + + /* Pilotwings uses DSP1 instead of DSP1B */ + if ( !memcmp( header->name, "PILOTWINGS", 10 ) ) + { + props->dsp_fw = DSPFW_1; + } + else + { + props->dsp_fw = DSPFW_1B; + } + } + else if ( header->map == 0x20 && header->carttype == 0x05 ) + { + props->has_dspx = 1; + props->dsp_fw = DSPFW_2; + props->fpga_features |= FEAT_DSPX; + } + else if ( header->map == 0x30 && header->carttype == 0x05 && header->licensee == 0xb2 ) + { + props->has_dspx = 1; + props->dsp_fw = DSPFW_3; + props->fpga_features |= FEAT_DSPX; + } + else if ( header->map == 0x30 && header->carttype == 0x03 ) + { + props->has_dspx = 1; + props->dsp_fw = DSPFW_4; + props->fpga_features |= FEAT_DSPX; + } + else if ( header->map == 0x30 && header->carttype == 0xf6 && header->romsize >= 0xa ) + { + props->has_dspx = 1; + props->has_st0010 = 1; + props->dsp_fw = DSPFW_ST0010; + props->fpga_features |= FEAT_ST0010; + header->ramsize = 2; + } + + break; case 0x25: /* ExHiROM */ - props->mapper_id = 2; - break; + props->mapper_id = 2; + break; case 0x22: /* ExLoROM */ - if(file_handle.fsize > 0x400200) { - props->mapper_id = 6; /* SO96 */ - } else { - props->mapper_id = 1; - } - break; + if ( file_handle.fsize > 0x400200 ) + { + props->mapper_id = 6; /* SO96 */ + } + else + { + props->mapper_id = 1; + } + + break; default: /* invalid/unsupported mapper, use header location */ - switch(score_idx) { + switch ( score_idx ) + { case 0: case 1: - props->mapper_id = 0; - break; + props->mapper_id = 0; + break; + case 2: case 3: - if(file_handle.fsize > 0x800200) { - props->mapper_id = 6; /* SO96 interleaved */ - } else if(file_handle.fsize > 0x400200) { - props->mapper_id = 1; /* ExLoROM */ - } else { - props->mapper_id = 1; /* LoROM */ - } - break; + if ( file_handle.fsize > 0x800200 ) + { + props->mapper_id = 6; /* SO96 interleaved */ + } + else if ( file_handle.fsize > 0x400200 ) + { + props->mapper_id = 1; /* ExLoROM */ + } + else + { + props->mapper_id = 1; /* LoROM */ + } + + break; + case 4: case 5: - props->mapper_id = 2; - break; - default: - props->mapper_id = 1; // whatever - } - } - if(header->romsize == 0 || header->romsize > 13) { - props->romsize_bytes = 1024; - header->romsize = 0; - if(file_handle.fsize >= 1024) { - while(props->romsize_bytes < file_handle.fsize-1) { - header->romsize++; - props->romsize_bytes <<= 1; - } - } - } - props->ramsize_bytes = (uint32_t)1024 << header->ramsize; - props->romsize_bytes = (uint32_t)1024 << header->romsize; - props->expramsize_bytes = (uint32_t)1024 << header->expramsize; - //dprintf("ramsize_bytes: %ld\n", props->ramsize_bytes); - if(props->ramsize_bytes > 32768 || props->ramsize_bytes < 2048) { - props->ramsize_bytes = 0; - } - props->region = (header->destcode <= 1 || header->destcode >= 13) ? 0 : 1; + props->mapper_id = 2; + break; -/*dprintf("ramsize_bytes: %ld\n", props->ramsize_bytes); */ + default: + props->mapper_id = 1; // whatever + } + } + + if ( header->romsize == 0 || header->romsize > 13 ) + { + props->romsize_bytes = 1024; + header->romsize = 0; + + if ( file_handle.fsize >= 1024 ) + { + while ( props->romsize_bytes < file_handle.fsize - 1 ) + { + header->romsize++; + props->romsize_bytes <<= 1; + } + } + } + + props->ramsize_bytes = ( uint32_t )1024 << header->ramsize; + props->romsize_bytes = ( uint32_t )1024 << header->romsize; + props->expramsize_bytes = ( uint32_t )1024 << header->expramsize; + + //dprintf("ramsize_bytes: %ld\n", props->ramsize_bytes); + if ( props->ramsize_bytes > 32768 || props->ramsize_bytes < 2048 ) + { + props->ramsize_bytes = 0; + } + + props->region = ( header->destcode <= 1 || header->destcode >= 13 ) ? 0 : 1; + + /*dprintf("ramsize_bytes: %ld\n", props->ramsize_bytes); */ } -uint8_t smc_headerscore(uint32_t addr, snes_header_t* header) { - int score=0; - uint8_t reset_inst; - uint16_t header_offset; - if((addr & 0xfff) == 0x1b0) { - header_offset = 0x200; - } else { - header_offset = 0; - } - if((file_readblock(header, addr, sizeof(snes_header_t)) < sizeof(snes_header_t)) - || file_res) { - return 0; - } - uint8_t mapper = header->map & ~0x10; - uint16_t resetvector = header->vect_reset; /* not endian safe! */ - uint32_t file_addr = (((addr - header_offset) & ~0x7fff) | (resetvector & 0x7fff)) + header_offset; - if(resetvector < 0x8000) return 0; +uint8_t smc_headerscore( uint32_t addr, snes_header_t *header ) +{ + int score = 0; + uint8_t reset_inst; + uint16_t header_offset; - score += 2*isFixed(&header->licensee, sizeof(header->licensee), 0x33); - score += 4*checkChksum(header->cchk, header->chk); - if(header->carttype < 0x08) score++; - if(header->romsize < 0x10) score++; - if(header->ramsize < 0x08) score++; - if(header->destcode < 0x0e) score++; + if ( ( addr & 0xfff ) == 0x1b0 ) + { + header_offset = 0x200; + } + else + { + header_offset = 0; + } - if((addr-header_offset) == 0x007fc0 && mapper == 0x20) score += 2; - if((addr-header_offset) == 0x00ffc0 && mapper == 0x21) score += 2; - if((addr-header_offset) == 0x007fc0 && mapper == 0x22) score += 2; - if((addr-header_offset) == 0x40ffc0 && mapper == 0x25) score += 2; + if ( ( file_readblock( header, addr, sizeof( snes_header_t ) ) < sizeof( snes_header_t ) ) + || file_res ) + { + return 0; + } - file_readblock(&reset_inst, file_addr, 1); - switch(reset_inst) { + uint8_t mapper = header->map & ~0x10; + uint16_t resetvector = header->vect_reset; /* not endian safe! */ + uint32_t file_addr = ( ( ( addr - header_offset ) & ~0x7fff ) | ( resetvector & 0x7fff ) ) + header_offset; + + if ( resetvector < 0x8000 ) + { + return 0; + } + + score += 2 * isFixed( &header->licensee, sizeof( header->licensee ), 0x33 ); + score += 4 * checkChksum( header->cchk, header->chk ); + + if ( header->carttype < 0x08 ) + { + score++; + } + + if ( header->romsize < 0x10 ) + { + score++; + } + + if ( header->ramsize < 0x08 ) + { + score++; + } + + if ( header->destcode < 0x0e ) + { + score++; + } + + if ( ( addr - header_offset ) == 0x007fc0 && mapper == 0x20 ) + { + score += 2; + } + + if ( ( addr - header_offset ) == 0x00ffc0 && mapper == 0x21 ) + { + score += 2; + } + + if ( ( addr - header_offset ) == 0x007fc0 && mapper == 0x22 ) + { + score += 2; + } + + if ( ( addr - header_offset ) == 0x40ffc0 && mapper == 0x25 ) + { + score += 2; + } + + file_readblock( &reset_inst, file_addr, 1 ); + + switch ( reset_inst ) + { case 0x78: /* sei */ case 0x18: /* clc */ case 0x38: /* sec */ case 0x9c: /* stz abs */ case 0x4c: /* jmp abs */ case 0x5c: /* jml abs */ - score += 8; - break; + score += 8; + break; case 0xc2: /* rep */ case 0xe2: /* sep */ @@ -260,8 +374,8 @@ uint8_t smc_headerscore(uint32_t addr, snes_header_t* header) { case 0xa0: /* ldy imm */ case 0x20: /* jsr abs */ case 0x22: /* jsl abs */ - score += 4; - break; + score += 4; + break; case 0x40: /* rti */ case 0x60: /* rts */ @@ -269,20 +383,28 @@ uint8_t smc_headerscore(uint32_t addr, snes_header_t* header) { case 0xcd: /* cmp abs */ case 0xec: /* cpx abs */ case 0xcc: /* cpy abs */ - score -= 4; - break; + score -= 4; + break; case 0x00: /* brk */ case 0x02: /* cop */ case 0xdb: /* stp */ case 0x42: /* wdm */ case 0xff: /* sbc abs long indexed */ - score -= 8; - break; - } + score -= 8; + break; + } - if(score && addr > 0x400000) score += 4; - if(score < 0) score = 0; - return score; + if ( score && addr > 0x400000 ) + { + score += 4; + } + + if ( score < 0 ) + { + score = 0; + } + + return score; } diff --git a/src/smc.h b/src/smc.h index a73843a..2c37b7b 100644 --- a/src/smc.h +++ b/src/smc.h @@ -37,57 +37,59 @@ #define FPGA_CX4 ((const uint8_t*)"/sd2snes/fpga_cx4.bit") -typedef struct _snes_header { - uint8_t maker[2]; /* 0xB0 */ - uint8_t gamecode[4]; /* 0xB2 */ - uint8_t fixed_00[7]; /* 0xB6 */ - uint8_t expramsize; /* 0xBD */ - uint8_t specver; /* 0xBE */ - uint8_t carttype2; /* 0xBF */ - uint8_t name[21]; /* 0xC0 */ - uint8_t map; /* 0xD5 */ - uint8_t carttype; /* 0xD6 */ - uint8_t romsize; /* 0xD7 */ - uint8_t ramsize; /* 0xD8 */ - uint8_t destcode; /* 0xD9 */ - uint8_t licensee; /* 0xDA */ - uint8_t ver; /* 0xDB */ - uint16_t cchk; /* 0xDC */ - uint16_t chk; /* 0xDE */ - uint32_t pad1; /* 0xE0 */ - uint16_t vect_cop16; /* 0xE4 */ - uint16_t vect_brk16; /* 0xE6 */ - uint16_t vect_abt16; /* 0xE8 */ - uint16_t vect_nmi16; /* 0xEA */ - uint16_t vect_irq16; /* 0xEE */ - uint16_t pad2; /* 0xF0 */ - uint16_t vect_cop8; /* 0xF4 */ - uint32_t pad3; /* 0xF6 */ - uint16_t vect_abt8; /* 0xF8 */ - uint16_t vect_nmi8; /* 0xFA */ - uint16_t vect_reset; /* 0xFC */ - uint16_t vect_brk8; /* 0xFE */ +typedef struct _snes_header +{ + uint8_t maker[2]; /* 0xB0 */ + uint8_t gamecode[4]; /* 0xB2 */ + uint8_t fixed_00[7]; /* 0xB6 */ + uint8_t expramsize; /* 0xBD */ + uint8_t specver; /* 0xBE */ + uint8_t carttype2; /* 0xBF */ + uint8_t name[21]; /* 0xC0 */ + uint8_t map; /* 0xD5 */ + uint8_t carttype; /* 0xD6 */ + uint8_t romsize; /* 0xD7 */ + uint8_t ramsize; /* 0xD8 */ + uint8_t destcode; /* 0xD9 */ + uint8_t licensee; /* 0xDA */ + uint8_t ver; /* 0xDB */ + uint16_t cchk; /* 0xDC */ + uint16_t chk; /* 0xDE */ + uint32_t pad1; /* 0xE0 */ + uint16_t vect_cop16; /* 0xE4 */ + uint16_t vect_brk16; /* 0xE6 */ + uint16_t vect_abt16; /* 0xE8 */ + uint16_t vect_nmi16; /* 0xEA */ + uint16_t vect_irq16; /* 0xEE */ + uint16_t pad2; /* 0xF0 */ + uint16_t vect_cop8; /* 0xF4 */ + uint32_t pad3; /* 0xF6 */ + uint16_t vect_abt8; /* 0xF8 */ + uint16_t vect_nmi8; /* 0xFA */ + uint16_t vect_reset; /* 0xFC */ + uint16_t vect_brk8; /* 0xFE */ } snes_header_t; -typedef struct _snes_romprops { - uint16_t offset; /* start of actual ROM image */ - uint8_t mapper_id; /* FPGA mapper */ - uint8_t pad1; /* for alignment */ - uint32_t expramsize_bytes; /* ExpRAM size in bytes */ - uint32_t ramsize_bytes; /* CartRAM size in bytes */ - uint32_t romsize_bytes; /* ROM size in bytes (rounded up) */ - const uint8_t* dsp_fw; /* DSP (NEC / Hitachi) ROM filename */ - const uint8_t* fpga_conf; /* FPGA config file to load (default: base) */ - uint8_t has_dspx; /* DSP[1-4] presence flag */ - uint8_t has_st0010; /* st0010 presence flag (additional to dspx) */ - uint8_t has_msu1; /* MSU1 presence flag */ - uint8_t has_cx4; /* CX4 presence flag */ - uint8_t fpga_features; /* feature/peripheral enable bits*/ - uint8_t region; /* game region (derived from destination code) */ - snes_header_t header; /* original header from ROM image */ +typedef struct _snes_romprops +{ + uint16_t offset; /* start of actual ROM image */ + uint8_t mapper_id; /* FPGA mapper */ + uint8_t pad1; /* for alignment */ + uint32_t expramsize_bytes; /* ExpRAM size in bytes */ + uint32_t ramsize_bytes; /* CartRAM size in bytes */ + uint32_t romsize_bytes; /* ROM size in bytes (rounded up) */ + const uint8_t *dsp_fw; /* DSP (NEC / Hitachi) ROM filename */ + const uint8_t *fpga_conf; /* FPGA config file to load (default: base) */ + uint8_t has_dspx; /* DSP[1-4] presence flag */ + uint8_t has_st0010; /* st0010 presence flag (additional to dspx) */ + uint8_t has_msu1; /* MSU1 presence flag */ + uint8_t has_cx4; /* CX4 presence flag */ + uint8_t fpga_features; /* feature/peripheral enable bits*/ + uint8_t region; /* game region (derived from destination code) */ + snes_header_t header; /* original header from ROM image */ } snes_romprops_t; -void smc_id(snes_romprops_t*); -uint8_t smc_headerscore(uint32_t addr, snes_header_t* header); +void smc_id( snes_romprops_t * ); +uint8_t smc_headerscore( uint32_t addr, snes_header_t *header ); #endif diff --git a/src/snes.c b/src/snes.c index c490065..1c9ac23 100644 --- a/src/snes.c +++ b/src/snes.c @@ -25,6 +25,7 @@ */ #include +#include #include "bits.h" #include "config.h" #include "uart.h" @@ -39,42 +40,51 @@ #include "fpga.h" #include "fpga_spi.h" -uint8_t initloop=1; +uint8_t initloop = 1; uint32_t saveram_crc, saveram_crc_old; extern snes_romprops_t romprops; volatile int reset_changed; volatile int reset_pressed; -void prepare_reset() { - snes_reset(1); - delay_ms(SNES_RESET_PULSELEN_MS); - if(romprops.ramsize_bytes && fpga_test() == FPGA_TEST_TOKEN) { - writeled(1); - save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR); - writeled(0); - } - rdyled(1); - readled(1); - writeled(1); - snes_reset(0); - while(get_snes_reset()); - snes_reset(1); - fpga_dspx_reset(1); - delay_ms(200); +void prepare_reset() +{ + snes_reset( 1 ); + delay_ms( SNES_RESET_PULSELEN_MS ); + + if ( romprops.ramsize_bytes && fpga_test() == FPGA_TEST_TOKEN ) + { + writeled( 1 ); + save_sram( file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR ); + writeled( 0 ); + } + + rdyled( 1 ); + readled( 1 ); + writeled( 1 ); + snes_reset( 0 ); + + while ( get_snes_reset() ); + + snes_reset( 1 ); + fpga_dspx_reset( 1 ); + delay_ms( 200 ); } -void snes_init() { - /* put reset level on reset pin */ - BITBAND(SNES_RESET_REG->FIOCLR, SNES_RESET_BIT) = 1; - /* reset the SNES */ - snes_reset(1); +void snes_init() +{ + /* put reset level on reset pin */ + BITBAND( SNES_RESET_REG->FIOCLR, SNES_RESET_BIT ) = 1; + + /* reset the SNES */ + snes_reset( 1 ); } -void snes_reset_pulse() { - snes_reset(1); - delay_ms(SNES_RESET_PULSELEN_MS); - snes_reset(0); +void snes_reset_pulse() +{ + snes_reset( 1 ); + delay_ms( SNES_RESET_PULSELEN_MS ); + snes_reset( 0 ); } /* @@ -82,12 +92,9 @@ void snes_reset_pulse() { * * state: put SNES in reset state when 1, release when 0 */ -void snes_reset(int state) { - if (state == 0) - printf("Releasing SNES RESET\n"); - else - printf("Pull SNES RESET\n"); - BITBAND(SNES_RESET_REG->FIODIR, SNES_RESET_BIT) = state; +void snes_reset( int state ) +{ + BITBAND( SNES_RESET_REG->FIODIR, SNES_RESET_BIT ) = state; } /* @@ -95,8 +102,9 @@ void snes_reset(int state) { * * returns: 1 when reset, 0 when not reset */ -uint8_t get_snes_reset() { - return !BITBAND(SNES_RESET_REG->FIOPIN, SNES_RESET_BIT); +uint8_t get_snes_reset() +{ + return !BITBAND( SNES_RESET_REG->FIOPIN, SNES_RESET_BIT ); } /* @@ -105,85 +113,123 @@ uint8_t get_snes_reset() { */ uint32_t diffcount = 0, samecount = 0, didnotsave = 0; uint8_t sram_valid = 0; -void snes_main_loop() { - if(!romprops.ramsize_bytes)return; - if(initloop) { - saveram_crc_old = calc_sram_crc(SRAM_SAVE_ADDR, romprops.ramsize_bytes); - initloop=0; - } - saveram_crc = calc_sram_crc(SRAM_SAVE_ADDR, romprops.ramsize_bytes); - sram_valid = sram_reliable(); - if(crc_valid && sram_valid) { - if(saveram_crc != saveram_crc_old) { - if(samecount) { - diffcount=1; - } else { - diffcount++; - didnotsave++; - } - samecount=0; +void snes_main_loop() +{ + if ( !romprops.ramsize_bytes ) + { + return; } - if(saveram_crc == saveram_crc_old) { - samecount++; + + if ( initloop ) + { + saveram_crc_old = calc_sram_crc( SRAM_SAVE_ADDR, romprops.ramsize_bytes ); + initloop = 0; } - if(diffcount>=1 && samecount==5) { - printf("SaveRAM CRC: 0x%04lx; saving %s\n", saveram_crc, file_lfn); - writeled(1); - save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR); - writeled(0); - didnotsave=0; + + saveram_crc = calc_sram_crc( SRAM_SAVE_ADDR, romprops.ramsize_bytes ); + sram_valid = sram_reliable(); + + if ( crc_valid && sram_valid ) + { + if ( saveram_crc != saveram_crc_old ) + { + if ( samecount ) + { + diffcount = 1; + } + else + { + diffcount++; + didnotsave++; + } + + samecount = 0; + } + + if ( saveram_crc == saveram_crc_old ) + { + samecount++; + } + + if ( diffcount >= 1 && samecount == 5 ) + { + printf( "SaveRAM CRC: 0x%04lx; saving %s\n", saveram_crc, file_lfn ); + writeled( 1 ); + save_sram( file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR ); + writeled( 0 ); + didnotsave = 0; + } + + if ( didnotsave > 50 ) + { + printf( "periodic save (sram contents keep changing...)\n" ); + diffcount = 0; + writeled( 1 ); + save_sram( file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR ); + didnotsave = 0; + writeled( 1 ); + } + + saveram_crc_old = saveram_crc; } - if(didnotsave>50) { - printf("periodic save (sram contents keep changing...)\n"); - diffcount=0; - writeled(1); - save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR); - didnotsave=0; - writeled(1); - } - saveram_crc_old = saveram_crc; - } - printf("crc=%lx crc_valid=%d sram_valid=%d diffcount=%ld samecount=%ld, didnotsave=%ld\n", saveram_crc, crc_valid, sram_valid, diffcount, samecount, didnotsave); + + printf( "crc=%lx crc_valid=%d sram_valid=%d diffcount=%ld samecount=%ld, didnotsave=%ld\n", saveram_crc, crc_valid, + sram_valid, diffcount, samecount, didnotsave ); } /* * SD2SNES menu loop. * monitors menu selection. return when selection was made. */ -uint8_t menu_main_loop() { - uint8_t cmd = 0; - sram_writebyte(0, SRAM_CMD_ADDR); - while(!cmd) { - if(!get_snes_reset()) { - while(!sram_reliable())printf("hurr\n"); - cmd = sram_readbyte(SRAM_CMD_ADDR); - } - if(get_snes_reset()) { - cmd = 0; - } - sleep_ms(20); - cli_entrycheck(); - } - return cmd; -} - -void get_selected_name(uint8_t* fn) { - uint32_t addr; - addr = sram_readlong(SRAM_PARAM_ADDR); - printf("fd addr=%lx\n", addr); - sram_readblock(fn, addr + 7 + SRAM_MENU_ADDR, 256); -} - -void snes_bootprint(void* msg) +uint8_t menu_main_loop() { - printf("%s\n", (char*)msg); - sram_writeblock(msg, SRAM_CMD_ADDR, 33); + uint8_t cmd = 0; + sram_writebyte( 0, SRAM_CMD_ADDR ); + + while ( !cmd ) + { + if ( !get_snes_reset() ) + { + while ( !sram_reliable() ) + { + printf( "hurr\n" ); + } + + cmd = sram_readbyte( SRAM_CMD_ADDR ); + //cmd = SNES_CMD_LOADSPC; + } + + if ( get_snes_reset() ) + { + cmd = 0; + } + + sleep_ms( 20 ); + cli_entrycheck(); + } + + return cmd; } -void snes_menu_errmsg(int err, void* msg) +void get_selected_name( uint8_t *fn ) { - printf("%d: %s\n", err, (char*)msg); - sram_writeblock(msg, SRAM_CMD_ADDR+1, 64); - sram_writebyte(err, SRAM_CMD_ADDR); + uint32_t addr; + addr = sram_readlong( SRAM_PARAM_ADDR ); + printf( "fd addr=%lx\n", addr ); + sram_readblock( fn, addr + 7 + SRAM_MENU_ADDR, 256 ); + //memcpy(fn, "dossier sans titre/ff6.sfc", 28); } - + +void snes_bootprint( void *msg ) +{ + printf( "SNES SAY: %s\n", ( char * )msg ); + sram_writeblock( msg, SRAM_CMD_ADDR, 33 ); +} + +void snes_menu_errmsg( int err, void *msg ) +{ + printf( "%d: %s\n", err, ( char * )msg ); + sram_writeblock( msg, SRAM_CMD_ADDR + 1, 64 ); + sram_writebyte( err, SRAM_CMD_ADDR ); +} + diff --git a/src/snes.h b/src/snes.h index 61725b7..104f69c 100644 --- a/src/snes.h +++ b/src/snes.h @@ -38,18 +38,18 @@ #define MENU_ERR_NODSP (1) #define MENU_ERR_NOBSX (2) -#define SNES_RESET_PULSELEN_MS (1) +#define SNES_RESET_PULSELEN_MS (100) uint8_t crc_valid; -void prepare_reset(void); -void snes_init(void); -void snes_reset_pulse(void); -void snes_reset(int state); -uint8_t get_snes_reset(void); -void snes_main_loop(void); -uint8_t menu_main_loop(void); -void get_selected_name(uint8_t* lfn); -void snes_bootprint(void* msg); -void snes_menu_errmsg(int err, void* msg); +void prepare_reset( void ); +void snes_init( void ); +void snes_reset_pulse( void ); +void snes_reset( int state ); +uint8_t get_snes_reset( void ); +void snes_main_loop( void ); +uint8_t menu_main_loop( void ); +void get_selected_name( uint8_t *lfn ); +void snes_bootprint( void *msg ); +void snes_menu_errmsg( int err, void *msg ); #endif diff --git a/src/snesboot.h b/src/snesboot.h index 87d6fda..8f294e2 100644 --- a/src/snesboot.h +++ b/src/snesboot.h @@ -1,330 +1,295 @@ const uint8_t bootrle[] = { - 0xe2, 0x20, 0xc2, 0x10, 0xa9, 0x00, 0x48, 0xab, - 0xad, 0x10, 0x42, 0xa2, 0x00, 0x58, 0x8e, 0x16, - 0x21, 0xa9, 0x01, 0x8d, 0x15, 0x00, 0xa2, 0x00, - 0xb0, 0xa9, 0x7f, 0x8e, 0x10, 0x00, 0x8d, 0x0f, - 0x00, 0xa2, 0x00, 0x09, 0x8e, 0x13, 0x00, 0xa9, - 0x18, 0x8d, 0x12, 0x00, 0x20, 0xdc, 0x0b, 0xa9, - 0x01, 0x8d, 0x16, 0x00, 0x6b, 0xe2, 0x20, 0xad, - 0x11, 0x42, 0x6b, 0xe2, 0x20, 0xc2, 0x10, 0x78, - 0x9c, 0x00, 0x42, 0x20, 0x2a, 0x01, 0xa9, 0x01, - 0x8d, 0x0d, 0x42, 0x20, 0x84, 0x02, 0x20, 0x93, - 0x01, 0x20, 0x8b, 0x01, 0x20, 0x04, 0x0c, 0x20, - 0x57, 0x02, 0xa2, 0x41, 0x00, 0xa9, 0x00, 0xca, - 0x9f, 0x00, 0x70, 0x30, 0xd0, 0xf9, 0xa9, 0x7e, - 0xa2, 0x1b, 0x00, 0x8d, 0x83, 0x21, 0x8e, 0x81, - 0x21, 0xa9, 0x00, 0x8d, 0x15, 0x00, 0xa2, 0xbc, - 0x00, 0xa9, 0xc0, 0x8e, 0x10, 0x00, 0x8d, 0x0f, - 0x00, 0xa2, 0x6f, 0x00, 0x8e, 0x13, 0x00, 0xa9, - 0x80, 0x8d, 0x12, 0x00, 0x20, 0xdc, 0x0b, 0xa9, - 0x7e, 0xa2, 0x8b, 0x00, 0x8d, 0x83, 0x21, 0x8e, - 0x81, 0x21, 0xa9, 0x00, 0x8d, 0x15, 0x00, 0xa2, - 0x8c, 0x0b, 0xa9, 0xc0, 0x8e, 0x10, 0x00, 0x8d, - 0x0f, 0x00, 0xa2, 0x4f, 0x00, 0x8e, 0x13, 0x00, - 0xa9, 0x80, 0x8d, 0x12, 0x00, 0x20, 0xdc, 0x0b, - 0x22, 0x1b, 0x00, 0x7e, 0xc2, 0x10, 0xe2, 0x20, - 0xa9, 0x00, 0x8f, 0x00, 0x00, 0x7e, 0xa9, 0x0d, - 0x8f, 0x02, 0x00, 0x7e, 0xa9, 0x30, 0x8f, 0x06, - 0x00, 0x7e, 0xc2, 0x20, 0xa9, 0x00, 0x70, 0x8f, - 0x04, 0x00, 0x7e, 0xe2, 0x20, 0xa9, 0x00, 0x8f, - 0x07, 0x00, 0x7e, 0x20, 0x8b, 0x00, 0xc2, 0x20, - 0xa9, 0x00, 0x58, 0x8d, 0x16, 0x21, 0xe2, 0x20, - 0xa9, 0x01, 0x8d, 0x00, 0x43, 0xa9, 0x18, 0x8d, - 0x01, 0x43, 0xa9, 0x7f, 0x8d, 0x04, 0x43, 0xa2, - 0x00, 0xb0, 0x8e, 0x02, 0x43, 0xa2, 0x00, 0x09, - 0x8e, 0x05, 0x43, 0xaf, 0x12, 0x42, 0x00, 0x29, - 0x80, 0xd0, 0xf8, 0xaf, 0x12, 0x42, 0x00, 0x29, - 0x80, 0xf0, 0xf8, 0xa9, 0x01, 0x8d, 0x0b, 0x42, - 0x80, 0x9a, 0x58, 0x9c, 0x00, 0x42, 0x5c, 0x19, - 0x00, 0x7e, 0x9c, 0x0b, 0x42, 0x9c, 0x0c, 0x42, - 0x9c, 0x10, 0x43, 0x9c, 0x11, 0x43, 0x9c, 0x12, - 0x43, 0x9c, 0x13, 0x43, 0x9c, 0x14, 0x43, 0x9c, - 0x20, 0x43, 0x9c, 0x21, 0x43, 0x9c, 0x22, 0x43, - 0x9c, 0x23, 0x43, 0x9c, 0x24, 0x43, 0x9c, 0x30, - 0x43, 0x9c, 0x31, 0x43, 0x9c, 0x32, 0x43, 0x9c, - 0x33, 0x43, 0x9c, 0x34, 0x43, 0x9c, 0x40, 0x43, - 0x9c, 0x41, 0x43, 0x9c, 0x42, 0x43, 0x9c, 0x43, - 0x43, 0x9c, 0x44, 0x43, 0x9c, 0x50, 0x43, 0x9c, - 0x51, 0x43, 0x9c, 0x52, 0x43, 0x9c, 0x53, 0x43, - 0x9c, 0x54, 0x43, 0x60, 0xad, 0x12, 0x42, 0x29, - 0x80, 0xd0, 0xf9, 0xad, 0x12, 0x42, 0x29, 0x80, - 0xf0, 0xf9, 0x60, 0xe2, 0x20, 0xc2, 0x10, 0x9c, - 0x30, 0x21, 0x60, 0xe2, 0x20, 0xc2, 0x10, 0x9c, - 0x00, 0x42, 0x9c, 0x0b, 0x42, 0x9c, 0x0c, 0x42, - 0xa2, 0x00, 0xb0, 0x8e, 0x81, 0x21, 0xa9, 0x01, - 0x8d, 0x83, 0x21, 0xa9, 0x08, 0x8d, 0x15, 0x00, - 0xa2, 0x59, 0xff, 0xa9, 0xc0, 0x8e, 0x10, 0x00, - 0x8d, 0x0f, 0x00, 0xa2, 0x40, 0x07, 0x8e, 0x13, - 0x00, 0xa9, 0x80, 0x8d, 0x12, 0x00, 0x20, 0xdc, - 0x0b, 0xa2, 0x00, 0x00, 0x8e, 0x16, 0x21, 0xa9, - 0x01, 0x8d, 0x15, 0x00, 0xa2, 0x7c, 0x03, 0xa9, - 0xc0, 0x8e, 0x10, 0x00, 0x8d, 0x0f, 0x00, 0xa2, - 0x00, 0x08, 0x8e, 0x13, 0x00, 0xa9, 0x18, 0x8d, - 0x12, 0x00, 0x20, 0xdc, 0x0b, 0xa2, 0x00, 0x58, - 0x8e, 0x16, 0x21, 0xa9, 0x09, 0x8d, 0x15, 0x00, - 0xa2, 0x59, 0xff, 0xa9, 0xc0, 0x8e, 0x10, 0x00, - 0x8d, 0x0f, 0x00, 0xa2, 0x40, 0x07, 0x8e, 0x13, - 0x00, 0xa9, 0x18, 0x8d, 0x12, 0x00, 0x20, 0xdc, - 0x0b, 0xa2, 0x00, 0x00, 0x8e, 0x02, 0x21, 0xa9, - 0x08, 0x8d, 0x15, 0x00, 0xa2, 0x59, 0xff, 0xa9, - 0xc0, 0x8e, 0x10, 0x00, 0x8d, 0x0f, 0x00, 0xa2, - 0x20, 0x02, 0x8e, 0x13, 0x00, 0xa9, 0x04, 0x8d, - 0x12, 0x00, 0x20, 0xdc, 0x0b, 0x9c, 0x21, 0x21, - 0xa9, 0x00, 0x8d, 0x15, 0x00, 0xa2, 0x7c, 0x0b, - 0xa9, 0xc0, 0x8e, 0x10, 0x00, 0x8d, 0x0f, 0x00, - 0xa2, 0x10, 0x00, 0x8e, 0x13, 0x00, 0xa9, 0x22, - 0x8d, 0x12, 0x00, 0x20, 0xdc, 0x0b, 0x60, 0xe2, - 0x20, 0xc2, 0x10, 0xa9, 0x00, 0x8d, 0x05, 0x21, - 0xa9, 0x58, 0x09, 0x02, 0x8d, 0x07, 0x21, 0xa9, - 0x40, 0x8d, 0x0b, 0x21, 0xa9, 0x01, 0x8d, 0x2c, - 0x21, 0xa9, 0x01, 0x8d, 0x2d, 0x21, 0xa9, 0x00, - 0x8d, 0x30, 0x21, 0x9c, 0x21, 0x21, 0xa9, 0x0f, - 0x8d, 0x00, 0x21, 0x60, 0xe2, 0x20, 0xc2, 0x10, - 0x9c, 0x00, 0x42, 0xa9, 0xff, 0x8d, 0x01, 0x42, - 0x9c, 0x02, 0x42, 0x9c, 0x03, 0x42, 0x9c, 0x04, - 0x42, 0x9c, 0x05, 0x42, 0x9c, 0x06, 0x42, 0x9c, - 0x07, 0x42, 0x9c, 0x08, 0x42, 0x9c, 0x09, 0x42, - 0x9c, 0x0a, 0x42, 0x9c, 0x0b, 0x42, 0x9c, 0x0c, - 0x42, 0xa9, 0x00, 0x8d, 0x0d, 0x42, 0xa9, 0x8f, - 0x8d, 0x00, 0x21, 0xa9, 0x03, 0x8d, 0x01, 0x21, - 0x9c, 0x02, 0x21, 0x9c, 0x03, 0x21, 0x9c, 0x05, - 0x21, 0x9c, 0x06, 0x21, 0x9c, 0x07, 0x21, 0x9c, - 0x08, 0x21, 0x9c, 0x09, 0x21, 0x9c, 0x0a, 0x21, - 0x9c, 0x0b, 0x21, 0x9c, 0x0c, 0x21, 0x9c, 0x0d, - 0x21, 0x9c, 0x0d, 0x21, 0x9c, 0x0e, 0x21, 0x9c, - 0x0e, 0x21, 0x9c, 0x0f, 0x21, 0x9c, 0x0f, 0x21, - 0xa9, 0x05, 0x8d, 0x10, 0x21, 0x9c, 0x10, 0x21, - 0x9c, 0x11, 0x21, 0x9c, 0x11, 0x21, 0x9c, 0x12, - 0x21, 0x9c, 0x12, 0x21, 0x9c, 0x13, 0x21, 0x9c, - 0x13, 0x21, 0x9c, 0x14, 0x21, 0x9c, 0x14, 0x21, - 0xa9, 0x80, 0x8d, 0x15, 0x21, 0x9c, 0x16, 0x21, - 0x9c, 0x17, 0x21, 0x9c, 0x1a, 0x21, 0x9c, 0x1b, - 0x21, 0xa9, 0x01, 0x8d, 0x1b, 0x21, 0x9c, 0x1c, - 0x21, 0x9c, 0x1c, 0x21, 0x9c, 0x1d, 0x21, 0x9c, - 0x1d, 0x21, 0x9c, 0x1e, 0x21, 0x8d, 0x1e, 0x21, - 0x9c, 0x1f, 0x21, 0x9c, 0x1f, 0x21, 0x9c, 0x20, - 0x21, 0x9c, 0x20, 0x21, 0x9c, 0x21, 0x21, 0x9c, - 0x23, 0x21, 0x9c, 0x24, 0x21, 0x9c, 0x25, 0x21, - 0x9c, 0x26, 0x21, 0x9c, 0x27, 0x21, 0x9c, 0x28, - 0x21, 0x9c, 0x29, 0x21, 0x9c, 0x2a, 0x21, 0x9c, - 0x2b, 0x21, 0x9c, 0x2c, 0x21, 0x9c, 0x2d, 0x21, - 0x9c, 0x2e, 0x21, 0xa9, 0x30, 0x8d, 0x30, 0x21, - 0x9c, 0x31, 0x21, 0xa9, 0xe0, 0x8d, 0x32, 0x21, - 0x9c, 0x33, 0x21, 0x60, 0x77, 0x00, 0x11, 0x02, - 0x30, 0x30, 0x48, 0x30, 0x48, 0x30, 0x48, 0x20, - 0x58, 0x00, 0x30, 0x30, 0x48, 0x00, 0x30, 0x00, - 0x6c, 0x6c, 0x92, 0x24, 0x5a, 0x00, 0x36, 0x5b, - 0x00, 0x09, 0x6c, 0x6c, 0x92, 0xfe, 0x01, 0x6c, - 0x92, 0xfe, 0x01, 0x6c, 0x92, 0x00, 0x6c, 0x00, - 0x00, 0x10, 0x6c, 0x7c, 0xc6, 0xc6, 0x39, 0xf0, - 0x0e, 0x1e, 0xe1, 0xc6, 0x39, 0x7c, 0xc6, 0x10, - 0x6c, 0x42, 0xa5, 0xa4, 0x5a, 0x48, 0xb4, 0x10, - 0x6c, 0x24, 0x5a, 0x4a, 0xb5, 0x84, 0x4a, 0x00, - 0x84, 0x70, 0xc8, 0xc0, 0x34, 0xc4, 0x2e, 0x6e, - 0xdb, 0xc4, 0x2a, 0xc4, 0x3a, 0x7c, 0xc6, 0x00, - 0x7c, 0x00, 0x18, 0x18, 0x24, 0x10, 0x28, 0x00, - 0x10, 0x5b, 0x00, 0x08, 0x18, 0x24, 0x30, 0x68, - 0x30, 0x48, 0x30, 0x48, 0x30, 0x48, 0x30, 0x68, - 0x18, 0x24, 0x00, 0x18, 0x30, 0x48, 0x18, 0x2c, - 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x2c, - 0x30, 0x48, 0x00, 0x30, 0x00, 0x6c, 0x6c, 0x92, - 0x38, 0x44, 0x7c, 0x82, 0x38, 0x44, 0x6c, 0x92, - 0x00, 0x6c, 0x00, 0x00, 0x00, 0x18, 0x18, 0x24, - 0x18, 0x66, 0x7e, 0x81, 0x18, 0x66, 0x18, 0x24, - 0x00, 0x18, 0x5b, 0x00, 0x0b, 0x18, 0x18, 0x24, - 0x18, 0x24, 0x10, 0x28, 0x5b, 0x00, 0x05, 0x7e, - 0x7e, 0x81, 0x00, 0x7e, 0x5b, 0x00, 0x0f, 0x18, - 0x18, 0x24, 0x18, 0x24, 0x00, 0x18, 0x03, 0x04, - 0x06, 0x09, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, - 0x60, 0x90, 0xc0, 0x20, 0x00, 0xc0, 0x7c, 0xc6, - 0xe6, 0x39, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29, - 0xce, 0x39, 0x7c, 0xc6, 0x00, 0x7c, 0x18, 0x34, - 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, - 0x18, 0x24, 0x18, 0x24, 0x00, 0x18, 0xfc, 0x06, - 0x06, 0xf9, 0x06, 0x79, 0x7c, 0x86, 0xc0, 0xbc, - 0xc0, 0x3e, 0xfe, 0x01, 0x00, 0xfe, 0xfc, 0x06, - 0x06, 0xf9, 0x06, 0x39, 0x3c, 0x46, 0x06, 0x39, - 0x06, 0xf9, 0xfc, 0x06, 0x00, 0xfc, 0xc6, 0x29, - 0xc6, 0x29, 0xc6, 0x39, 0x7e, 0xc1, 0x06, 0x79, - 0x06, 0x09, 0x06, 0x09, 0x00, 0x06, 0xfe, 0x01, - 0xc0, 0x3e, 0xc0, 0x3c, 0xfc, 0x06, 0x06, 0xf9, - 0x06, 0xf9, 0xfc, 0x06, 0x00, 0xf8, 0x7c, 0xc2, - 0xc0, 0x3c, 0xc0, 0x3c, 0xfc, 0x06, 0xc6, 0x39, - 0xc6, 0x39, 0x7c, 0xc6, 0x00, 0x7c, 0xfc, 0x06, - 0x06, 0xf9, 0x06, 0x09, 0x06, 0x09, 0x06, 0x09, - 0x06, 0x09, 0x06, 0x09, 0x00, 0x06, 0x7c, 0xc6, - 0xc6, 0x39, 0xc6, 0x39, 0x7c, 0xc6, 0xc6, 0x39, - 0xc6, 0x39, 0x7c, 0xc6, 0x00, 0x7c, 0x7c, 0xc6, - 0xc6, 0x39, 0xc6, 0x39, 0x7e, 0xc1, 0x06, 0x79, - 0x06, 0x79, 0x7c, 0x86, 0x00, 0x7c, 0x00, 0x00, - 0x00, 0x30, 0x30, 0x48, 0x00, 0x30, 0x00, 0x30, - 0x30, 0x48, 0x00, 0x30, 0x5b, 0x00, 0x05, 0x30, - 0x30, 0x48, 0x00, 0x30, 0x00, 0x30, 0x30, 0x48, - 0x20, 0x50, 0x00, 0x20, 0x00, 0x18, 0x18, 0x24, - 0x30, 0x48, 0x60, 0x90, 0x30, 0x48, 0x18, 0x24, - 0x00, 0x18, 0x5b, 0x00, 0x05, 0x3c, 0x3c, 0x42, - 0x00, 0x3c, 0x00, 0x3c, 0x3c, 0x42, 0x00, 0x3c, - 0x00, 0x00, 0x00, 0x30, 0x30, 0x48, 0x18, 0x24, - 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x00, 0x30, - 0x00, 0x00, 0xf8, 0x0c, 0x0c, 0xf2, 0x0c, 0x12, - 0x18, 0x24, 0x30, 0x48, 0x00, 0x30, 0x30, 0x48, - 0x00, 0x30, 0x7c, 0xc6, 0xc6, 0x39, 0xc6, 0x39, - 0xde, 0x21, 0xde, 0x21, 0xc0, 0x3e, 0x7e, 0xc1, - 0x00, 0x7e, 0x7c, 0xc6, 0xc6, 0x39, 0xc6, 0x39, - 0xde, 0x21, 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29, - 0x00, 0xc6, 0xfc, 0x06, 0xc6, 0x39, 0xc6, 0x39, - 0xdc, 0x26, 0xc6, 0x39, 0xc6, 0x39, 0xfc, 0x06, - 0x00, 0xfc, 0x7e, 0xc1, 0xc0, 0x3e, 0xc0, 0x20, - 0xc0, 0x20, 0xc0, 0x20, 0xc0, 0x3e, 0x7e, 0xc1, - 0x00, 0x7e, 0xfc, 0x02, 0xc6, 0x3b, 0xc6, 0x29, - 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x3b, 0xfc, 0x02, - 0x00, 0xfc, 0xfe, 0x01, 0xc0, 0x3e, 0xc0, 0x38, - 0xf8, 0x04, 0xc0, 0x38, 0xc0, 0x3e, 0xfe, 0x01, - 0x00, 0xfe, 0xfe, 0x01, 0xc0, 0x3e, 0xc0, 0x38, - 0xf8, 0x04, 0xc0, 0x38, 0xc0, 0x20, 0xc0, 0x20, - 0x00, 0xc0, 0x7e, 0xc1, 0xc0, 0x3e, 0xc0, 0x2e, - 0xce, 0x33, 0xc6, 0x29, 0xc6, 0x39, 0x7c, 0xc6, - 0x00, 0x7c, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39, - 0xfe, 0x01, 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29, - 0x00, 0xc6, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, - 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, - 0x00, 0x18, 0x0c, 0x12, 0x0c, 0x12, 0x0c, 0x12, - 0x0c, 0x12, 0x0c, 0x12, 0x0c, 0xf6, 0xf8, 0x06, - 0x00, 0xfc, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x38, - 0xfc, 0x06, 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29, - 0x00, 0xc7, 0xc0, 0x20, 0xc0, 0x20, 0xc0, 0x20, - 0xc0, 0x20, 0xc0, 0x20, 0xc0, 0x3c, 0xfc, 0x02, - 0x00, 0xfc, 0xec, 0x16, 0xd6, 0x29, 0xd6, 0x29, - 0xd6, 0x29, 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29, - 0x00, 0xc7, 0xfc, 0x06, 0xc6, 0x39, 0xc6, 0x29, - 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29, - 0x00, 0xc6, 0x7c, 0xc6, 0xc6, 0x39, 0xc6, 0x29, - 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39, 0x7c, 0xc6, - 0x00, 0x7c, 0xfc, 0x06, 0xc6, 0x39, 0xc6, 0x29, - 0xc6, 0x39, 0xfc, 0x06, 0xc0, 0x3c, 0xc0, 0x20, - 0x00, 0xc0, 0x7c, 0x82, 0xc6, 0xbb, 0xc6, 0x29, - 0xc6, 0x29, 0xc6, 0x29, 0xce, 0x31, 0x7e, 0xc1, - 0x00, 0x7e, 0xfc, 0x06, 0xc6, 0x39, 0xc6, 0x39, - 0xfc, 0x06, 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29, - 0x00, 0xc6, 0x7e, 0xc1, 0xc0, 0x3e, 0xc0, 0x3c, - 0x7c, 0xc6, 0x06, 0x79, 0x06, 0xf9, 0xfc, 0x06, - 0x00, 0xfc, 0xfe, 0x01, 0x18, 0xe6, 0x18, 0x24, - 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, - 0x00, 0x18, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29, - 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39, 0x7c, 0xc6, - 0x00, 0x7c, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29, - 0xc6, 0x29, 0x66, 0x99, 0x36, 0x49, 0x1e, 0x21, - 0x00, 0x1f, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39, - 0xd6, 0x29, 0xd6, 0x29, 0xd6, 0x29, 0x6e, 0xd1, - 0x00, 0x6e, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39, - 0x7c, 0xc6, 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29, - 0x00, 0xc6, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39, - 0x7e, 0xc1, 0x06, 0x79, 0x06, 0xf9, 0xfc, 0x06, - 0x00, 0xfc, 0xfe, 0x01, 0x06, 0xf9, 0x06, 0x79, - 0x7c, 0xc6, 0xc0, 0x3c, 0xc0, 0x3e, 0xfe, 0x01, - 0x00, 0xfe, 0x3c, 0x42, 0x30, 0x4c, 0x30, 0x48, - 0x30, 0x48, 0x30, 0x48, 0x30, 0x4c, 0x3c, 0x42, - 0x00, 0x3c, 0xc0, 0x20, 0x60, 0x90, 0x30, 0x48, - 0x18, 0x24, 0x0c, 0x12, 0x06, 0x09, 0x03, 0x04, - 0x00, 0x03, 0x3c, 0x42, 0x0c, 0x32, 0x0c, 0x12, - 0x0c, 0x12, 0x0c, 0x12, 0x0c, 0x32, 0x3c, 0x42, - 0x00, 0x3c, 0x18, 0x24, 0x3c, 0x66, 0x66, 0x99, - 0x00, 0x66, 0x5b, 0x00, 0x13, 0x7e, 0x7e, 0x81, - 0x00, 0x7e, 0x30, 0x48, 0x18, 0x24, 0x18, 0x24, - 0x00, 0x18, 0x5b, 0x00, 0x0b, 0x7c, 0x7c, 0x86, - 0x06, 0x79, 0x7e, 0xc1, 0xc6, 0x39, 0x7e, 0xc1, - 0x00, 0x7e, 0xc0, 0x20, 0xc0, 0x3c, 0xfc, 0x06, - 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x39, 0xfc, 0x06, - 0x00, 0xfc, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0xc1, - 0xc0, 0x3e, 0xc0, 0x20, 0xc0, 0x3e, 0x7e, 0xc1, - 0x00, 0x7e, 0x06, 0x09, 0x06, 0x79, 0x7e, 0xc1, - 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x39, 0x7e, 0xc1, - 0x00, 0x7f, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0xc6, - 0xc6, 0x39, 0xfe, 0x01, 0xc0, 0x3e, 0x7e, 0xc3, - 0x00, 0x7e, 0x1e, 0x21, 0x30, 0x6e, 0x30, 0x4c, - 0x3c, 0x42, 0x30, 0x4c, 0x30, 0x48, 0x30, 0x48, - 0x30, 0x48, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0xc1, - 0xc6, 0x39, 0xc6, 0x39, 0x7e, 0xc1, 0x06, 0x79, - 0x7c, 0x86, 0xc0, 0x20, 0xc0, 0x3c, 0xfc, 0x06, - 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29, - 0x00, 0xc6, 0x00, 0x18, 0x18, 0x24, 0x00, 0x18, - 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, - 0x00, 0x18, 0x00, 0x18, 0x18, 0x24, 0x00, 0x18, - 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x2c, - 0x30, 0x48, 0xc0, 0x20, 0xc0, 0x26, 0xc6, 0x29, - 0xc6, 0x2b, 0xfc, 0x06, 0xc6, 0x2b, 0xc6, 0x29, - 0x00, 0xc7, 0x30, 0x48, 0x30, 0x48, 0x30, 0x48, - 0x30, 0x48, 0x30, 0x48, 0x30, 0x68, 0x18, 0x24, - 0x00, 0x1c, 0x00, 0x00, 0x00, 0xec, 0xec, 0x16, - 0xd6, 0x29, 0xd6, 0x29, 0xd6, 0x29, 0xc6, 0x39, - 0x00, 0xc7, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0x06, - 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29, - 0x00, 0xc6, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0xc6, - 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x39, 0x7c, 0xc6, - 0x00, 0x7c, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0x06, - 0xc6, 0x39, 0xc6, 0x39, 0xfc, 0x06, 0xc0, 0x3c, - 0xc0, 0x20, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0xc1, - 0xc6, 0x39, 0xc6, 0x39, 0x7e, 0xc1, 0x06, 0x79, - 0x06, 0x09, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0xc2, - 0xc0, 0x3c, 0xc0, 0x20, 0xc0, 0x20, 0xc0, 0x20, - 0x00, 0xc0, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0xc1, - 0xc0, 0x3e, 0x7c, 0xc6, 0x06, 0xf9, 0xfc, 0x06, - 0x00, 0xfc, 0x30, 0x48, 0x30, 0x4c, 0x3c, 0x42, - 0x30, 0x4c, 0x30, 0x48, 0x30, 0x4e, 0x1e, 0x31, - 0x00, 0x1e, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x29, - 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39, 0x7c, 0xc6, - 0x00, 0x7c, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x29, - 0xc6, 0x29, 0x66, 0x99, 0x36, 0x49, 0x1e, 0x21, - 0x00, 0x1e, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x39, - 0xd6, 0x29, 0xd6, 0x29, 0xd6, 0x29, 0x6e, 0xd1, - 0x00, 0x6e, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x29, - 0xc6, 0x39, 0x7c, 0xc6, 0xc6, 0x39, 0xc6, 0x29, - 0x00, 0xc6, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x29, - 0xc6, 0x39, 0x7e, 0xc1, 0x06, 0x79, 0x06, 0xf9, - 0xfc, 0x06, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x01, - 0x06, 0xf9, 0x7c, 0xc6, 0xc0, 0x3e, 0xfe, 0x01, - 0x00, 0xfe, 0x18, 0x24, 0x30, 0x48, 0x30, 0x48, - 0x70, 0x88, 0x30, 0x48, 0x30, 0x48, 0x18, 0x24, - 0x00, 0x18, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, - 0x00, 0x18, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, - 0x00, 0x18, 0x30, 0x48, 0x18, 0x24, 0x18, 0x24, - 0x1c, 0x22, 0x18, 0x24, 0x18, 0x24, 0x30, 0x48, - 0x00, 0x30, 0x00, 0x00, 0x00, 0x72, 0x72, 0x9d, - 0xfe, 0x01, 0x9c, 0x72, 0x00, 0x9c, 0x5b, 0x00, - 0x14, 0x42, 0x08, 0xff, 0x7f, 0x00, 0x00, 0x9c, - 0x73, 0x42, 0x08, 0xff, 0x43, 0x00, 0x00, 0x18, - 0x63, 0xc2, 0x30, 0xad, 0x00, 0x00, 0x29, 0xff, - 0x00, 0x0a, 0x18, 0x69, 0x00, 0xb0, 0x8d, 0x09, - 0x00, 0xad, 0x02, 0x00, 0x29, 0xff, 0x00, 0x5b, - 0x0a, 0x06, 0x18, 0x6d, 0x09, 0x00, 0x8f, 0x81, - 0x21, 0x00, 0xe2, 0x20, 0xa9, 0x7f, 0x8f, 0x83, - 0x21, 0x00, 0xae, 0x04, 0x00, 0xad, 0x06, 0x00, - 0x48, 0xab, 0xbd, 0x00, 0x00, 0xf0, 0x11, 0x8f, - 0x80, 0x21, 0x00, 0xa9, 0x00, 0x69, 0x00, 0x09, - 0x20, 0x8f, 0x80, 0x21, 0x00, 0xe8, 0x80, 0xea, - 0xa9, 0x00, 0x48, 0xab, 0x60, 0xff, 0xc2, 0x10, - 0xe2, 0x20, 0xad, 0x15, 0x00, 0x8d, 0x00, 0x43, - 0xad, 0x12, 0x00, 0x8d, 0x01, 0x43, 0xad, 0x0f, - 0x00, 0xae, 0x10, 0x00, 0x8e, 0x02, 0x43, 0x8d, - 0x04, 0x43, 0xae, 0x13, 0x00, 0x8e, 0x05, 0x43, - 0xa9, 0x01, 0x8d, 0x0b, 0x42, 0x60, 0xe2, 0x20, - 0xc2, 0x10, 0x9c, 0x0b, 0x42, 0x9c, 0x0c, 0x42, - 0x9c, 0x00, 0x42, 0x60, 0x77, 0x00, 0xee, 0xf2, - 0x78, 0x18, 0xfb, 0x5c, 0x3b, 0x00, 0xc0, 0x08, - 0xc2, 0x30, 0x48, 0xda, 0x5a, 0x0b, 0x8b, 0x22, - 0x35, 0x00, 0xc0, 0xc2, 0x30, 0xab, 0x2b, 0x7a, - 0xfa, 0x68, 0x28, 0x40, 0x08, 0xc2, 0x30, 0x48, - 0xda, 0x5a, 0x0b, 0x8b, 0x22, 0x00, 0x00, 0xc0, - 0xc2, 0x30, 0xab, 0x2b, 0x7a, 0xfa, 0x68, 0x28, - 0x40, 0xcb, 0xaf, 0xef, 0xcd, 0xab, 0x80, 0xf9, - 0x5b, 0x20, 0x1c, 0x76, 0x30, 0x2e, 0x31, 0x00, - 0x00, 0x00, 0x5b, 0x20, 0x41, 0x00, 0x20, 0x3c, - 0x64, 0x69, 0x72, 0x3e, 0x5b, 0x00, 0x0d, 0x4d, - 0x52, 0x42, 0x4f, 0x4f, 0x54, 0x5b, 0x00, 0x0a, - 0x53, 0x44, 0x32, 0x53, 0x4e, 0x45, 0x53, 0x20, - 0x42, 0x4f, 0x4f, 0x54, 0x5b, 0x20, 0x09, 0x31, - 0x02, 0x06, 0x03, 0x09, 0x33, 0x00, 0x4f, 0x87, - 0xb0, 0x78, 0x5b, 0x00, 0x04, 0x31, 0xff, 0x31, - 0xff, 0x31, 0xff, 0x1c, 0xff, 0x00, 0x00, 0x07, - 0xff, 0x5b, 0x00, 0x04, 0x31, 0xff, 0x00, 0x00, - 0x31, 0xff, 0x31, 0xff, 0x00, 0xff, 0x31, 0xff}; +0xE2, 0x20, 0xC2, 0x10, 0xA9, 0x00, 0x48, 0xAB, 0xAD, +0x10, 0x42, 0xA2, 0x00, 0x58, 0x8E, 0x16, 0x21, 0xA9, +0x01, 0x8D, 0x15, 0x00, 0xA2, 0x00, 0xB0, 0xA9, 0x7F, +0x8E, 0x10, 0x00, 0x8D, 0x0F, 0x00, 0xA2, 0x00, 0x09, +0x8E, 0x13, 0x00, 0xA9, 0x18, 0x8D, 0x12, 0x00, 0x20, +0xDC, 0x0B, 0xA9, 0x01, 0x8D, 0x16, 0x00, 0x6B, 0xE2, +0x20, 0xAD, 0x11, 0x42, 0x6B, 0xE2, 0x20, 0xC2, 0x10, +0x78, 0x9C, 0x00, 0x42, 0x20, 0x2A, 0x01, 0xA9, 0x01, +0x8D, 0x0D, 0x42, 0x20, 0x84, 0x02, 0x20, 0x93, 0x01, +0x20, 0x8B, 0x01, 0x20, 0x04, 0x0C, 0x20, 0x57, 0x02, +0xA2, 0x41, 0x00, 0xA9, 0x00, 0xCA, 0x9F, 0x00, 0x70, +0x30, 0xD0, 0xF9, 0xA9, 0x7E, 0xA2, 0x1B, 0x00, 0x8D, +0x83, 0x21, 0x8E, 0x81, 0x21, 0xA9, 0x00, 0x8D, 0x15, +0x00, 0xA2, 0xBC, 0x00, 0xA9, 0xC0, 0x8E, 0x10, 0x00, +0x8D, 0x0F, 0x00, 0xA2, 0x6F, 0x00, 0x8E, 0x13, 0x00, +0xA9, 0x80, 0x8D, 0x12, 0x00, 0x20, 0xDC, 0x0B, 0xA9, +0x7E, 0xA2, 0x8B, 0x00, 0x8D, 0x83, 0x21, 0x8E, 0x81, +0x21, 0xA9, 0x00, 0x8D, 0x15, 0x00, 0xA2, 0x8C, 0x0B, +0xA9, 0xC0, 0x8E, 0x10, 0x00, 0x8D, 0x0F, 0x00, 0xA2, +0x4F, 0x00, 0x8E, 0x13, 0x00, 0xA9, 0x80, 0x8D, 0x12, +0x00, 0x20, 0xDC, 0x0B, 0x22, 0x1B, 0x00, 0x7E, 0xC2, +0x10, 0xE2, 0x20, 0xA9, 0x00, 0x8F, 0x00, 0x00, 0x7E, +0xA9, 0x0D, 0x8F, 0x02, 0x00, 0x7E, 0xA9, 0x30, 0x8F, +0x06, 0x00, 0x7E, 0xC2, 0x20, 0xA9, 0x00, 0x70, 0x8F, +0x04, 0x00, 0x7E, 0xE2, 0x20, 0xA9, 0x00, 0x8F, 0x07, +0x00, 0x7E, 0x20, 0x8B, 0x00, 0xC2, 0x20, 0xA9, 0x00, +0x58, 0x8D, 0x16, 0x21, 0xE2, 0x20, 0xA9, 0x01, 0x8D, +0x00, 0x43, 0xA9, 0x18, 0x8D, 0x01, 0x43, 0xA9, 0x7F, +0x8D, 0x04, 0x43, 0xA2, 0x00, 0xB0, 0x8E, 0x02, 0x43, +0xA2, 0x00, 0x09, 0x8E, 0x05, 0x43, 0xAF, 0x12, 0x42, +0x00, 0x29, 0x80, 0xD0, 0xF8, 0xAF, 0x12, 0x42, 0x00, +0x29, 0x80, 0xF0, 0xF8, 0xA9, 0x01, 0x8D, 0x0B, 0x42, +0x80, 0x9A, 0x58, 0x9C, 0x00, 0x42, 0x5C, 0x19, 0x00, +0x7E, 0x9C, 0x0B, 0x42, 0x9C, 0x0C, 0x42, 0x9C, 0x10, +0x43, 0x9C, 0x11, 0x43, 0x9C, 0x12, 0x43, 0x9C, 0x13, +0x43, 0x9C, 0x14, 0x43, 0x9C, 0x20, 0x43, 0x9C, 0x21, +0x43, 0x9C, 0x22, 0x43, 0x9C, 0x23, 0x43, 0x9C, 0x24, +0x43, 0x9C, 0x30, 0x43, 0x9C, 0x31, 0x43, 0x9C, 0x32, +0x43, 0x9C, 0x33, 0x43, 0x9C, 0x34, 0x43, 0x9C, 0x40, +0x43, 0x9C, 0x41, 0x43, 0x9C, 0x42, 0x43, 0x9C, 0x43, +0x43, 0x9C, 0x44, 0x43, 0x9C, 0x50, 0x43, 0x9C, 0x51, +0x43, 0x9C, 0x52, 0x43, 0x9C, 0x53, 0x43, 0x9C, 0x54, +0x43, 0x60, 0xAD, 0x12, 0x42, 0x29, 0x80, 0xD0, 0xF9, +0xAD, 0x12, 0x42, 0x29, 0x80, 0xF0, 0xF9, 0x60, 0xE2, +0x20, 0xC2, 0x10, 0x9C, 0x30, 0x21, 0x60, 0xE2, 0x20, +0xC2, 0x10, 0x9C, 0x00, 0x42, 0x9C, 0x0B, 0x42, 0x9C, +0x0C, 0x42, 0xA2, 0x00, 0xB0, 0x8E, 0x81, 0x21, 0xA9, +0x01, 0x8D, 0x83, 0x21, 0xA9, 0x08, 0x8D, 0x15, 0x00, +0xA2, 0x59, 0xFF, 0xA9, 0xC0, 0x8E, 0x10, 0x00, 0x8D, +0x0F, 0x00, 0xA2, 0x40, 0x07, 0x8E, 0x13, 0x00, 0xA9, +0x80, 0x8D, 0x12, 0x00, 0x20, 0xDC, 0x0B, 0xA2, 0x00, +0x00, 0x8E, 0x16, 0x21, 0xA9, 0x01, 0x8D, 0x15, 0x00, +0xA2, 0x7C, 0x03, 0xA9, 0xC0, 0x8E, 0x10, 0x00, 0x8D, +0x0F, 0x00, 0xA2, 0x00, 0x08, 0x8E, 0x13, 0x00, 0xA9, +0x18, 0x8D, 0x12, 0x00, 0x20, 0xDC, 0x0B, 0xA2, 0x00, +0x58, 0x8E, 0x16, 0x21, 0xA9, 0x09, 0x8D, 0x15, 0x00, +0xA2, 0x59, 0xFF, 0xA9, 0xC0, 0x8E, 0x10, 0x00, 0x8D, +0x0F, 0x00, 0xA2, 0x40, 0x07, 0x8E, 0x13, 0x00, 0xA9, +0x18, 0x8D, 0x12, 0x00, 0x20, 0xDC, 0x0B, 0xA2, 0x00, +0x00, 0x8E, 0x02, 0x21, 0xA9, 0x08, 0x8D, 0x15, 0x00, +0xA2, 0x59, 0xFF, 0xA9, 0xC0, 0x8E, 0x10, 0x00, 0x8D, +0x0F, 0x00, 0xA2, 0x20, 0x02, 0x8E, 0x13, 0x00, 0xA9, +0x04, 0x8D, 0x12, 0x00, 0x20, 0xDC, 0x0B, 0x9C, 0x21, +0x21, 0xA9, 0x00, 0x8D, 0x15, 0x00, 0xA2, 0x7C, 0x0B, +0xA9, 0xC0, 0x8E, 0x10, 0x00, 0x8D, 0x0F, 0x00, 0xA2, +0x10, 0x00, 0x8E, 0x13, 0x00, 0xA9, 0x22, 0x8D, 0x12, +0x00, 0x20, 0xDC, 0x0B, 0x60, 0xE2, 0x20, 0xC2, 0x10, +0xA9, 0x00, 0x8D, 0x05, 0x21, 0xA9, 0x58, 0x09, 0x02, +0x8D, 0x07, 0x21, 0xA9, 0x40, 0x8D, 0x0B, 0x21, 0xA9, +0x01, 0x8D, 0x2C, 0x21, 0xA9, 0x01, 0x8D, 0x2D, 0x21, +0xA9, 0x00, 0x8D, 0x30, 0x21, 0x9C, 0x21, 0x21, 0xA9, +0x0F, 0x8D, 0x00, 0x21, 0x60, 0xE2, 0x20, 0xC2, 0x10, +0x9C, 0x00, 0x42, 0xA9, 0xFF, 0x8D, 0x01, 0x42, 0x9C, +0x02, 0x42, 0x9C, 0x03, 0x42, 0x9C, 0x04, 0x42, 0x9C, +0x05, 0x42, 0x9C, 0x06, 0x42, 0x9C, 0x07, 0x42, 0x9C, +0x08, 0x42, 0x9C, 0x09, 0x42, 0x9C, 0x0A, 0x42, 0x9C, +0x0B, 0x42, 0x9C, 0x0C, 0x42, 0xA9, 0x00, 0x8D, 0x0D, +0x42, 0xA9, 0x8F, 0x8D, 0x00, 0x21, 0xA9, 0x03, 0x8D, +0x01, 0x21, 0x9C, 0x02, 0x21, 0x9C, 0x03, 0x21, 0x9C, +0x05, 0x21, 0x9C, 0x06, 0x21, 0x9C, 0x07, 0x21, 0x9C, +0x08, 0x21, 0x9C, 0x09, 0x21, 0x9C, 0x0A, 0x21, 0x9C, +0x0B, 0x21, 0x9C, 0x0C, 0x21, 0x9C, 0x0D, 0x21, 0x9C, +0x0D, 0x21, 0x9C, 0x0E, 0x21, 0x9C, 0x0E, 0x21, 0x9C, +0x0F, 0x21, 0x9C, 0x0F, 0x21, 0xA9, 0x05, 0x8D, 0x10, +0x21, 0x9C, 0x10, 0x21, 0x9C, 0x11, 0x21, 0x9C, 0x11, +0x21, 0x9C, 0x12, 0x21, 0x9C, 0x12, 0x21, 0x9C, 0x13, +0x21, 0x9C, 0x13, 0x21, 0x9C, 0x14, 0x21, 0x9C, 0x14, +0x21, 0xA9, 0x80, 0x8D, 0x15, 0x21, 0x9C, 0x16, 0x21, +0x9C, 0x17, 0x21, 0x9C, 0x1A, 0x21, 0x9C, 0x1B, 0x21, +0xA9, 0x01, 0x8D, 0x1B, 0x21, 0x9C, 0x1C, 0x21, 0x9C, +0x1C, 0x21, 0x9C, 0x1D, 0x21, 0x9C, 0x1D, 0x21, 0x9C, +0x1E, 0x21, 0x8D, 0x1E, 0x21, 0x9C, 0x1F, 0x21, 0x9C, +0x1F, 0x21, 0x9C, 0x20, 0x21, 0x9C, 0x20, 0x21, 0x9C, +0x21, 0x21, 0x9C, 0x23, 0x21, 0x9C, 0x24, 0x21, 0x9C, +0x25, 0x21, 0x9C, 0x26, 0x21, 0x9C, 0x27, 0x21, 0x9C, +0x28, 0x21, 0x9C, 0x29, 0x21, 0x9C, 0x2A, 0x21, 0x9C, +0x2B, 0x21, 0x9C, 0x2C, 0x21, 0x9C, 0x2D, 0x21, 0x9C, +0x2E, 0x21, 0xA9, 0x30, 0x8D, 0x30, 0x21, 0x9C, 0x31, +0x21, 0xA9, 0xE0, 0x8D, 0x32, 0x21, 0x9C, 0x33, 0x21, +0x60, 0x77, 0x00, 0x11, 0x02, 0x30, 0x30, 0x48, 0x30, +0x48, 0x30, 0x48, 0x20, 0x58, 0x00, 0x30, 0x30, 0x48, +0x00, 0x30, 0x00, 0x6C, 0x6C, 0x92, 0x24, 0x5A, 0x00, +0x36, 0x5B, 0x00, 0x09, 0x6C, 0x6C, 0x92, 0xFE, 0x01, +0x6C, 0x92, 0xFE, 0x01, 0x6C, 0x92, 0x00, 0x6C, 0x00, +0x00, 0x10, 0x6C, 0x7C, 0xC6, 0xC6, 0x39, 0xF0, 0x0E, +0x1E, 0xE1, 0xC6, 0x39, 0x7C, 0xC6, 0x10, 0x6C, 0x42, +0xA5, 0xA4, 0x5A, 0x48, 0xB4, 0x10, 0x6C, 0x24, 0x5A, +0x4A, 0xB5, 0x84, 0x4A, 0x00, 0x84, 0x70, 0xC8, 0xC0, +0x34, 0xC4, 0x2E, 0x6E, 0xDB, 0xC4, 0x2A, 0xC4, 0x3A, +0x7C, 0xC6, 0x00, 0x7C, 0x00, 0x18, 0x18, 0x24, 0x10, +0x28, 0x00, 0x10, 0x5B, 0x00, 0x08, 0x18, 0x24, 0x30, +0x68, 0x30, 0x48, 0x30, 0x48, 0x30, 0x48, 0x30, 0x68, +0x18, 0x24, 0x00, 0x18, 0x30, 0x48, 0x18, 0x2C, 0x18, +0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x2C, 0x30, 0x48, +0x00, 0x30, 0x00, 0x6C, 0x6C, 0x92, 0x38, 0x44, 0x7C, +0x82, 0x38, 0x44, 0x6C, 0x92, 0x00, 0x6C, 0x00, 0x00, +0x00, 0x18, 0x18, 0x24, 0x18, 0x66, 0x7E, 0x81, 0x18, +0x66, 0x18, 0x24, 0x00, 0x18, 0x5B, 0x00, 0x0B, 0x18, +0x18, 0x24, 0x18, 0x24, 0x10, 0x28, 0x5B, 0x00, 0x05, +0x7E, 0x7E, 0x81, 0x00, 0x7E, 0x5B, 0x00, 0x0F, 0x18, +0x18, 0x24, 0x18, 0x24, 0x00, 0x18, 0x03, 0x04, 0x06, +0x09, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x90, +0xC0, 0x20, 0x00, 0xC0, 0x7C, 0xC6, 0xE6, 0x39, 0xC6, +0x29, 0xC6, 0x29, 0xC6, 0x29, 0xCE, 0x39, 0x7C, 0xC6, +0x00, 0x7C, 0x18, 0x34, 0x18, 0x24, 0x18, 0x24, 0x18, +0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x00, 0x18, +0xFC, 0x06, 0x06, 0xF9, 0x06, 0x79, 0x7C, 0x86, 0xC0, +0xBC, 0xC0, 0x3E, 0xFE, 0x01, 0x00, 0xFE, 0xFC, 0x06, +0x06, 0xF9, 0x06, 0x39, 0x3C, 0x46, 0x06, 0x39, 0x06, +0xF9, 0xFC, 0x06, 0x00, 0xFC, 0xC6, 0x29, 0xC6, 0x29, +0xC6, 0x39, 0x7E, 0xC1, 0x06, 0x79, 0x06, 0x09, 0x06, +0x09, 0x00, 0x06, 0xFE, 0x01, 0xC0, 0x3E, 0xC0, 0x3C, +0xFC, 0x06, 0x06, 0xF9, 0x06, 0xF9, 0xFC, 0x06, 0x00, +0xF8, 0x7C, 0xC2, 0xC0, 0x3C, 0xC0, 0x3C, 0xFC, 0x06, +0xC6, 0x39, 0xC6, 0x39, 0x7C, 0xC6, 0x00, 0x7C, 0xFC, +0x06, 0x06, 0xF9, 0x06, 0x09, 0x06, 0x09, 0x06, 0x09, +0x06, 0x09, 0x06, 0x09, 0x00, 0x06, 0x7C, 0xC6, 0xC6, +0x39, 0xC6, 0x39, 0x7C, 0xC6, 0xC6, 0x39, 0xC6, 0x39, +0x7C, 0xC6, 0x00, 0x7C, 0x7C, 0xC6, 0xC6, 0x39, 0xC6, +0x39, 0x7E, 0xC1, 0x06, 0x79, 0x06, 0x79, 0x7C, 0x86, +0x00, 0x7C, 0x00, 0x00, 0x00, 0x30, 0x30, 0x48, 0x00, +0x30, 0x00, 0x30, 0x30, 0x48, 0x00, 0x30, 0x5B, 0x00, +0x05, 0x30, 0x30, 0x48, 0x00, 0x30, 0x00, 0x30, 0x30, +0x48, 0x20, 0x50, 0x00, 0x20, 0x00, 0x18, 0x18, 0x24, +0x30, 0x48, 0x60, 0x90, 0x30, 0x48, 0x18, 0x24, 0x00, +0x18, 0x5B, 0x00, 0x05, 0x3C, 0x3C, 0x42, 0x00, 0x3C, +0x00, 0x3C, 0x3C, 0x42, 0x00, 0x3C, 0x00, 0x00, 0x00, +0x30, 0x30, 0x48, 0x18, 0x24, 0x0C, 0x12, 0x18, 0x24, +0x30, 0x48, 0x00, 0x30, 0x00, 0x00, 0xF8, 0x0C, 0x0C, +0xF2, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x00, 0x30, +0x30, 0x48, 0x00, 0x30, 0x7C, 0xC6, 0xC6, 0x39, 0xC6, +0x39, 0xDE, 0x21, 0xDE, 0x21, 0xC0, 0x3E, 0x7E, 0xC1, +0x00, 0x7E, 0x7C, 0xC6, 0xC6, 0x39, 0xC6, 0x39, 0xDE, +0x21, 0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x29, 0x00, 0xC6, +0xFC, 0x06, 0xC6, 0x39, 0xC6, 0x39, 0xDC, 0x26, 0xC6, +0x39, 0xC6, 0x39, 0xFC, 0x06, 0x00, 0xFC, 0x7E, 0xC1, +0xC0, 0x3E, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, +0x3E, 0x7E, 0xC1, 0x00, 0x7E, 0xFC, 0x02, 0xC6, 0x3B, +0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x3B, 0xFC, +0x02, 0x00, 0xFC, 0xFE, 0x01, 0xC0, 0x3E, 0xC0, 0x38, +0xF8, 0x04, 0xC0, 0x38, 0xC0, 0x3E, 0xFE, 0x01, 0x00, +0xFE, 0xFE, 0x01, 0xC0, 0x3E, 0xC0, 0x38, 0xF8, 0x04, +0xC0, 0x38, 0xC0, 0x20, 0xC0, 0x20, 0x00, 0xC0, 0x7E, +0xC1, 0xC0, 0x3E, 0xC0, 0x2E, 0xCE, 0x33, 0xC6, 0x29, +0xC6, 0x39, 0x7C, 0xC6, 0x00, 0x7C, 0xC6, 0x29, 0xC6, +0x29, 0xC6, 0x39, 0xFE, 0x01, 0xC6, 0x39, 0xC6, 0x29, +0xC6, 0x29, 0x00, 0xC6, 0x18, 0x24, 0x18, 0x24, 0x18, +0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, +0x00, 0x18, 0x0C, 0x12, 0x0C, 0x12, 0x0C, 0x12, 0x0C, +0x12, 0x0C, 0x12, 0x0C, 0xF6, 0xF8, 0x06, 0x00, 0xFC, +0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x38, 0xFC, 0x06, 0xC6, +0x39, 0xC6, 0x29, 0xC6, 0x29, 0x00, 0xC7, 0xC0, 0x20, +0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, +0x3C, 0xFC, 0x02, 0x00, 0xFC, 0xEC, 0x16, 0xD6, 0x29, +0xD6, 0x29, 0xD6, 0x29, 0xC6, 0x39, 0xC6, 0x29, 0xC6, +0x29, 0x00, 0xC7, 0xFC, 0x06, 0xC6, 0x39, 0xC6, 0x29, +0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x29, 0x00, +0xC6, 0x7C, 0xC6, 0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x29, +0xC6, 0x29, 0xC6, 0x39, 0x7C, 0xC6, 0x00, 0x7C, 0xFC, +0x06, 0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x39, 0xFC, 0x06, +0xC0, 0x3C, 0xC0, 0x20, 0x00, 0xC0, 0x7C, 0x82, 0xC6, +0xBB, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x29, 0xCE, 0x31, +0x7E, 0xC1, 0x00, 0x7E, 0xFC, 0x06, 0xC6, 0x39, 0xC6, +0x39, 0xFC, 0x06, 0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x29, +0x00, 0xC6, 0x7E, 0xC1, 0xC0, 0x3E, 0xC0, 0x3C, 0x7C, +0xC6, 0x06, 0x79, 0x06, 0xF9, 0xFC, 0x06, 0x00, 0xFC, +0xFE, 0x01, 0x18, 0xE6, 0x18, 0x24, 0x18, 0x24, 0x18, +0x24, 0x18, 0x24, 0x18, 0x24, 0x00, 0x18, 0xC6, 0x29, +0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x29, 0xC6, +0x39, 0x7C, 0xC6, 0x00, 0x7C, 0xC6, 0x29, 0xC6, 0x29, +0xC6, 0x29, 0xC6, 0x29, 0x66, 0x99, 0x36, 0x49, 0x1E, +0x21, 0x00, 0x1F, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x39, +0xD6, 0x29, 0xD6, 0x29, 0xD6, 0x29, 0x6E, 0xD1, 0x00, +0x6E, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x39, 0x7C, 0xC6, +0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x29, 0x00, 0xC6, 0xC6, +0x29, 0xC6, 0x29, 0xC6, 0x39, 0x7E, 0xC1, 0x06, 0x79, +0x06, 0xF9, 0xFC, 0x06, 0x00, 0xFC, 0xFE, 0x01, 0x06, +0xF9, 0x06, 0x79, 0x7C, 0xC6, 0xC0, 0x3C, 0xC0, 0x3E, +0xFE, 0x01, 0x00, 0xFE, 0x3C, 0x42, 0x30, 0x4C, 0x30, +0x48, 0x30, 0x48, 0x30, 0x48, 0x30, 0x4C, 0x3C, 0x42, +0x00, 0x3C, 0xC0, 0x20, 0x60, 0x90, 0x30, 0x48, 0x18, +0x24, 0x0C, 0x12, 0x06, 0x09, 0x03, 0x04, 0x00, 0x03, +0x3C, 0x42, 0x0C, 0x32, 0x0C, 0x12, 0x0C, 0x12, 0x0C, +0x12, 0x0C, 0x32, 0x3C, 0x42, 0x00, 0x3C, 0x18, 0x24, +0x3C, 0x66, 0x66, 0x99, 0x00, 0x66, 0x5B, 0x00, 0x13, +0x7E, 0x7E, 0x81, 0x00, 0x7E, 0x30, 0x48, 0x18, 0x24, +0x18, 0x24, 0x00, 0x18, 0x5B, 0x00, 0x0B, 0x7C, 0x7C, +0x86, 0x06, 0x79, 0x7E, 0xC1, 0xC6, 0x39, 0x7E, 0xC1, +0x00, 0x7E, 0xC0, 0x20, 0xC0, 0x3C, 0xFC, 0x06, 0xC6, +0x39, 0xC6, 0x29, 0xC6, 0x39, 0xFC, 0x06, 0x00, 0xFC, +0x00, 0x00, 0x00, 0x7E, 0x7E, 0xC1, 0xC0, 0x3E, 0xC0, +0x20, 0xC0, 0x3E, 0x7E, 0xC1, 0x00, 0x7E, 0x06, 0x09, +0x06, 0x79, 0x7E, 0xC1, 0xC6, 0x39, 0xC6, 0x29, 0xC6, +0x39, 0x7E, 0xC1, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7C, +0x7C, 0xC6, 0xC6, 0x39, 0xFE, 0x01, 0xC0, 0x3E, 0x7E, +0xC3, 0x00, 0x7E, 0x1E, 0x21, 0x30, 0x6E, 0x30, 0x4C, +0x3C, 0x42, 0x30, 0x4C, 0x30, 0x48, 0x30, 0x48, 0x30, +0x48, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0xC1, 0xC6, 0x39, +0xC6, 0x39, 0x7E, 0xC1, 0x06, 0x79, 0x7C, 0x86, 0xC0, +0x20, 0xC0, 0x3C, 0xFC, 0x06, 0xC6, 0x39, 0xC6, 0x29, +0xC6, 0x29, 0xC6, 0x29, 0x00, 0xC6, 0x00, 0x18, 0x18, +0x24, 0x00, 0x18, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, +0x18, 0x24, 0x00, 0x18, 0x00, 0x18, 0x18, 0x24, 0x00, +0x18, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x2C, +0x30, 0x48, 0xC0, 0x20, 0xC0, 0x26, 0xC6, 0x29, 0xC6, +0x2B, 0xFC, 0x06, 0xC6, 0x2B, 0xC6, 0x29, 0x00, 0xC7, +0x30, 0x48, 0x30, 0x48, 0x30, 0x48, 0x30, 0x48, 0x30, +0x48, 0x30, 0x68, 0x18, 0x24, 0x00, 0x1C, 0x00, 0x00, +0x00, 0xEC, 0xEC, 0x16, 0xD6, 0x29, 0xD6, 0x29, 0xD6, +0x29, 0xC6, 0x39, 0x00, 0xC7, 0x00, 0x00, 0x00, 0xFC, +0xFC, 0x06, 0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x29, 0xC6, +0x29, 0x00, 0xC6, 0x00, 0x00, 0x00, 0x7C, 0x7C, 0xC6, +0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x39, 0x7C, 0xC6, 0x00, +0x7C, 0x00, 0x00, 0x00, 0xFC, 0xFC, 0x06, 0xC6, 0x39, +0xC6, 0x39, 0xFC, 0x06, 0xC0, 0x3C, 0xC0, 0x20, 0x00, +0x00, 0x00, 0x7E, 0x7E, 0xC1, 0xC6, 0x39, 0xC6, 0x39, +0x7E, 0xC1, 0x06, 0x79, 0x06, 0x09, 0x00, 0x00, 0x00, +0x7C, 0x7C, 0xC2, 0xC0, 0x3C, 0xC0, 0x20, 0xC0, 0x20, +0xC0, 0x20, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x7E, 0x7E, +0xC1, 0xC0, 0x3E, 0x7C, 0xC6, 0x06, 0xF9, 0xFC, 0x06, +0x00, 0xFC, 0x30, 0x48, 0x30, 0x4C, 0x3C, 0x42, 0x30, +0x4C, 0x30, 0x48, 0x30, 0x4E, 0x1E, 0x31, 0x00, 0x1E, +0x00, 0x00, 0x00, 0xC6, 0xC6, 0x29, 0xC6, 0x29, 0xC6, +0x29, 0xC6, 0x39, 0x7C, 0xC6, 0x00, 0x7C, 0x00, 0x00, +0x00, 0xC6, 0xC6, 0x29, 0xC6, 0x29, 0x66, 0x99, 0x36, +0x49, 0x1E, 0x21, 0x00, 0x1E, 0x00, 0x00, 0x00, 0xC6, +0xC6, 0x39, 0xD6, 0x29, 0xD6, 0x29, 0xD6, 0x29, 0x6E, +0xD1, 0x00, 0x6E, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0x29, +0xC6, 0x39, 0x7C, 0xC6, 0xC6, 0x39, 0xC6, 0x29, 0x00, +0xC6, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0x29, 0xC6, 0x39, +0x7E, 0xC1, 0x06, 0x79, 0x06, 0xF9, 0xFC, 0x06, 0x00, +0x00, 0x00, 0xFE, 0xFE, 0x01, 0x06, 0xF9, 0x7C, 0xC6, +0xC0, 0x3E, 0xFE, 0x01, 0x00, 0xFE, 0x18, 0x24, 0x30, +0x48, 0x30, 0x48, 0x70, 0x88, 0x30, 0x48, 0x30, 0x48, +0x18, 0x24, 0x00, 0x18, 0x18, 0x24, 0x18, 0x24, 0x18, +0x24, 0x00, 0x18, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, +0x00, 0x18, 0x30, 0x48, 0x18, 0x24, 0x18, 0x24, 0x1C, +0x22, 0x18, 0x24, 0x18, 0x24, 0x30, 0x48, 0x00, 0x30, +0x00, 0x00, 0x00, 0x72, 0x72, 0x9D, 0xFE, 0x01, 0x9C, +0x72, 0x00, 0x9C, 0x5B, 0x00, 0x14, 0x42, 0x08, 0xFF, +0x7F, 0x00, 0x00, 0x9C, 0x73, 0x42, 0x08, 0xFF, 0x43, +0x00, 0x00, 0x18, 0x63, 0xC2, 0x30, 0xAD, 0x00, 0x00, +0x29, 0xFF, 0x00, 0x0A, 0x18, 0x69, 0x00, 0xB0, 0x8D, +0x09, 0x00, 0xAD, 0x02, 0x00, 0x29, 0xFF, 0x00, 0x5B, +0x0A, 0x06, 0x18, 0x6D, 0x09, 0x00, 0x8F, 0x81, 0x21, +0x00, 0xE2, 0x20, 0xA9, 0x7F, 0x8F, 0x83, 0x21, 0x00, +0xAE, 0x04, 0x00, 0xAD, 0x06, 0x00, 0x48, 0xAB, 0xBD, +0x00, 0x00, 0xF0, 0x11, 0x8F, 0x80, 0x21, 0x00, 0xA9, +0x00, 0x69, 0x00, 0x09, 0x20, 0x8F, 0x80, 0x21, 0x00, +0xE8, 0x80, 0xEA, 0xA9, 0x00, 0x48, 0xAB, 0x60, 0xFF, +0xC2, 0x10, 0xE2, 0x20, 0xAD, 0x15, 0x00, 0x8D, 0x00, +0x43, 0xAD, 0x12, 0x00, 0x8D, 0x01, 0x43, 0xAD, 0x0F, +0x00, 0xAE, 0x10, 0x00, 0x8E, 0x02, 0x43, 0x8D, 0x04, +0x43, 0xAE, 0x13, 0x00, 0x8E, 0x05, 0x43, 0xA9, 0x01, +0x8D, 0x0B, 0x42, 0x60, 0xE2, 0x20, 0xC2, 0x10, 0x9C, +0x0B, 0x42, 0x9C, 0x0C, 0x42, 0x9C, 0x00, 0x42, 0x60, +0x77, 0x00, 0xEE, 0xF2, 0x78, 0x18, 0xFB, 0x5C, 0x3B, +0x00, 0xC0, 0x08, 0xC2, 0x30, 0x48, 0xDA, 0x5A, 0x0B, +0x8B, 0x22, 0x35, 0x00, 0xC0, 0xC2, 0x30, 0xAB, 0x2B, +0x7A, 0xFA, 0x68, 0x28, 0x40, 0x08, 0xC2, 0x30, 0x48, +0xDA, 0x5A, 0x0B, 0x8B, 0x22, 0x00, 0x00, 0xC0, 0xC2, +0x30, 0xAB, 0x2B, 0x7A, 0xFA, 0x68, 0x28, 0x40, 0xCB, +0xAF, 0xEF, 0xCD, 0xAB, 0x80, 0xF9, 0x5B, 0x20, 0x1C, +0x76, 0x30, 0x2E, 0x31, 0x00, 0x00, 0x00, 0x5B, 0x20, +0x41, 0x00, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x3E, 0x5B, +0x00, 0x0D, 0x4D, 0x52, 0x42, 0x4F, 0x4F, 0x54, 0x5B, +0x00, 0x0A, 0x53, 0x44, 0x32, 0x53, 0x4E, 0x45, 0x53, +0x20, 0x42, 0x4F, 0x4F, 0x54, 0x5B, 0x20, 0x09, 0x31, +0x02, 0x06, 0x03, 0x09, 0x33, 0x00, 0x4F, 0x87, 0xB0, +0x78, 0x5B, 0x00, 0x04, 0x31, 0xFF, 0x31, 0xFF, 0x31, +0xFF, 0x1C, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x5B, 0x00, +0x04, 0x31, 0xFF, 0x00, 0x00, 0x31, 0xFF, 0x31, 0xFF, +0x00, 0xFF, 0x31, 0xFF, 0xFF, +}; \ No newline at end of file diff --git a/src/sort.c b/src/sort.c index 962d62e..db9ddf8 100644 --- a/src/sort.c +++ b/src/sort.c @@ -7,120 +7,163 @@ #include "memory.h" #include "sort.h" -/* - heap sort algorithm for data located outside RAM +/* + heap sort algorithm for data located outside RAM addr: start address of pointer table i: index (in 32-bit elements) heapsize: size of heap (in 32-bit elements) */ uint32_t stat_getstring = 0; -static char sort_str1[SORT_STRLEN+1], sort_str2[SORT_STRLEN+1]; +static char sort_str1[SORT_STRLEN + 1], sort_str2[SORT_STRLEN + 1]; uint32_t ptrcache[QSORT_MAXELEM] IN_AHBRAM; /* get element from pointer table in external RAM*/ -uint32_t sort_get_elem(uint32_t base, unsigned int index) { - return sram_readlong(base+4*index); +uint32_t sort_get_elem( uint32_t base, unsigned int index ) +{ + return sram_readlong( base + 4 * index ); } /* put element from pointer table in external RAM */ -void sort_put_elem(uint32_t base, unsigned int index, uint32_t elem) { - sram_writelong(elem, base+4*index); +void sort_put_elem( uint32_t base, unsigned int index, uint32_t elem ) +{ + sram_writelong( elem, base + 4 * index ); } /* compare strings pointed to by elements of pointer table */ -int sort_cmp_idx(uint32_t base, unsigned int index1, unsigned int index2) { - uint32_t elem1, elem2; - elem1 = sort_get_elem(base, index1); - elem2 = sort_get_elem(base, index2); - return sort_cmp_elem((void*)&elem1, (void*)&elem2); +int sort_cmp_idx( uint32_t base, unsigned int index1, unsigned int index2 ) +{ + uint32_t elem1, elem2; + elem1 = sort_get_elem( base, index1 ); + elem2 = sort_get_elem( base, index2 ); + return sort_cmp_elem( ( void * )&elem1, ( void * )&elem2 ); } -int sort_cmp_elem(const void* elem1, const void* elem2) { - uint32_t el1 = *(uint32_t*)elem1; - uint32_t el2 = *(uint32_t*)elem2; - sort_getstring_for_dirent(sort_str1, el1); - sort_getstring_for_dirent(sort_str2, el2); -/*printf("i1=%d i2=%d elem1=%lx elem2=%lx ; compare %s --- %s\n", index1, index2, elem1, elem2, sort_str1, sort_str2); */ +int sort_cmp_elem( const void *elem1, const void *elem2 ) +{ + uint32_t el1 = *( uint32_t * )elem1; + uint32_t el2 = *( uint32_t * )elem2; + sort_getstring_for_dirent( sort_str1, el1 ); + sort_getstring_for_dirent( sort_str2, el2 ); + /*printf("i1=%d i2=%d elem1=%lx elem2=%lx ; compare %s --- %s\n", index1, index2, elem1, elem2, sort_str1, sort_str2); */ - if ((el1 & 0x80000000) && !(el2 & 0x80000000)) { - return -1; - } + if ( ( el1 & 0x80000000 ) && !( el2 & 0x80000000 ) ) + { + return -1; + } - if (!(el1 & 0x80000000) && (el2 & 0x80000000)) { - return 1; - } + if ( !( el1 & 0x80000000 ) && ( el2 & 0x80000000 ) ) + { + return 1; + } - if (*sort_str1 == '.') return -1; - if (*sort_str2 == '.') return 1; + if ( *sort_str1 == '.' ) + { + return -1; + } - /* Do not compare trailing slashes of directory names */ - if ((el1 & 0x80000000) && (el2 & 0x80000000)) { - char *str1_slash = strrchr(sort_str1, '/'); - char *str2_slash = strrchr(sort_str2, '/'); - if(str1_slash != NULL) *str1_slash = 0; - if(str2_slash != NULL) *str2_slash = 0; - } + if ( *sort_str2 == '.' ) + { + return 1; + } - return strcasecmp(sort_str1, sort_str2); + /* Do not compare trailing slashes of directory names */ + if ( ( el1 & 0x80000000 ) && ( el2 & 0x80000000 ) ) + { + char *str1_slash = strrchr( sort_str1, '/' ); + char *str2_slash = strrchr( sort_str2, '/' ); + + if ( str1_slash != NULL ) + { + *str1_slash = 0; + } + + if ( str2_slash != NULL ) + { + *str2_slash = 0; + } + } + + return strcasecmp( sort_str1, sort_str2 ); } /* get truncated string from database */ -void sort_getstring_for_dirent(char *ptr, uint32_t addr) { - uint8_t leaf_offset; - if(addr & 0x80000000) { - /* is directory link, name offset 4 */ - leaf_offset = sram_readbyte(addr + 4 + SRAM_MENU_ADDR); - sram_readstrn(ptr, addr + 5 + leaf_offset + SRAM_MENU_ADDR, SORT_STRLEN); - } else { - /* is file link, name offset 6 */ - leaf_offset = sram_readbyte(addr + 6 + SRAM_MENU_ADDR); - sram_readstrn(ptr, addr + 7 + leaf_offset + SRAM_MENU_ADDR, SORT_STRLEN); - } -} - -void sort_heapify(uint32_t addr, unsigned int i, unsigned int heapsize) +void sort_getstring_for_dirent( char *ptr, uint32_t addr ) { - while(1) { - unsigned int l = 2*i+1; - unsigned int r = 2*i+2; - unsigned int largest = (l < heapsize && sort_cmp_idx(addr, i, l) < 0) ? l : i; + uint8_t leaf_offset; - if(r < heapsize && sort_cmp_idx(addr, largest, r) < 0) - largest = r; - - if(largest != i) { - uint32_t tmp = sort_get_elem(addr, i); - sort_put_elem(addr, i, sort_get_elem(addr, largest)); - sort_put_elem(addr, largest, tmp); - i = largest; + if ( addr & 0x80000000 ) + { + /* is directory link, name offset 4 */ + leaf_offset = sram_readbyte( addr + 4 + SRAM_MENU_ADDR ); + sram_readstrn( ptr, addr + 5 + leaf_offset + SRAM_MENU_ADDR, SORT_STRLEN ); + } + else + { + /* is file link, name offset 6 */ + leaf_offset = sram_readbyte( addr + 6 + SRAM_MENU_ADDR ); + sram_readstrn( ptr, addr + 7 + leaf_offset + SRAM_MENU_ADDR, SORT_STRLEN ); } - else break; - } } -void sort_dir(uint32_t addr, unsigned int size) +void sort_heapify( uint32_t addr, unsigned int i, unsigned int heapsize ) { -stat_getstring=0; - if(size > QSORT_MAXELEM) { - printf("more than %d dir entries, doing slower in-place sort\n", QSORT_MAXELEM); - ext_heapsort(addr, size); - } else { - /* retrieve, sort, and store dir table */ - sram_readblock(ptrcache, addr, size*4); - qsort((void*)ptrcache, size, 4, sort_cmp_elem); - sram_writeblock(ptrcache, addr, size*4); - } + while ( 1 ) + { + unsigned int l = 2 * i + 1; + unsigned int r = 2 * i + 2; + unsigned int largest = ( l < heapsize && sort_cmp_idx( addr, i, l ) < 0 ) ? l : i; + + if ( r < heapsize && sort_cmp_idx( addr, largest, r ) < 0 ) + { + largest = r; + } + + if ( largest != i ) + { + uint32_t tmp = sort_get_elem( addr, i ); + sort_put_elem( addr, i, sort_get_elem( addr, largest ) ); + sort_put_elem( addr, largest, tmp ); + i = largest; + } + else + { + break; + } + } } -void ext_heapsort(uint32_t addr, unsigned int size) { - for(unsigned int i = size/2; i > 0;) sort_heapify(addr, --i, size); +void sort_dir( uint32_t addr, unsigned int size ) +{ + stat_getstring = 0; - for(unsigned int i = size-1; i>0; --i) { - uint32_t tmp = sort_get_elem(addr, 0); - sort_put_elem(addr, 0, sort_get_elem(addr, i)); - sort_put_elem(addr, i, tmp); - sort_heapify(addr, 0, i); - } + if ( size > QSORT_MAXELEM ) + { + printf( "more than %d dir entries, doing slower in-place sort\n", QSORT_MAXELEM ); + ext_heapsort( addr, size ); + } + else + { + /* retrieve, sort, and store dir table */ + sram_readblock( ptrcache, addr, size * 4 ); + qsort( ( void * )ptrcache, size, 4, sort_cmp_elem ); + sram_writeblock( ptrcache, addr, size * 4 ); + } +} + +void ext_heapsort( uint32_t addr, unsigned int size ) +{ + for ( unsigned int i = size / 2; i > 0; ) + { + sort_heapify( addr, --i, size ); + } + + for ( unsigned int i = size - 1; i > 0; --i ) + { + uint32_t tmp = sort_get_elem( addr, 0 ); + sort_put_elem( addr, 0, sort_get_elem( addr, i ) ); + sort_put_elem( addr, i, tmp ); + sort_heapify( addr, 0, i ); + } } diff --git a/src/sort.h b/src/sort.h index bb3ff00..a33cf6f 100644 --- a/src/sort.h +++ b/src/sort.h @@ -3,13 +3,13 @@ #include -uint32_t sort_get_elem(uint32_t base, unsigned int index); -void sort_put_elem(uint32_t base, unsigned int index, uint32_t elem); -int sort_cmp_idx(uint32_t base, unsigned int index1, unsigned int index2); -int sort_cmp_elem(const void* elem1, const void* elem2); -void sort_getstring_for_dirent(char *ptr, uint32_t addr); -void sort_getlong_for_dirent(uint32_t* ptr, uint32_t addr); -void sort_heapify(uint32_t addr, unsigned int i, unsigned int heapsize); -void sort_dir(uint32_t addr, unsigned int size); -void ext_heapsort(uint32_t addr, unsigned int size); +uint32_t sort_get_elem( uint32_t base, unsigned int index ); +void sort_put_elem( uint32_t base, unsigned int index, uint32_t elem ); +int sort_cmp_idx( uint32_t base, unsigned int index1, unsigned int index2 ); +int sort_cmp_elem( const void *elem1, const void *elem2 ); +void sort_getstring_for_dirent( char *ptr, uint32_t addr ); +void sort_getlong_for_dirent( uint32_t *ptr, uint32_t addr ); +void sort_heapify( uint32_t addr, unsigned int i, unsigned int heapsize ); +void sort_dir( uint32_t addr, unsigned int size ); +void ext_heapsort( uint32_t addr, unsigned int size ); #endif diff --git a/src/spi.c b/src/spi.c index f3c6a6f..75bf90a 100644 --- a/src/spi.c +++ b/src/spi.c @@ -30,154 +30,176 @@ #include "spi.h" #include "uart.h" -void spi_preinit() { - - /* Set clock prescaler to 1:1 */ - BITBAND(LPC_SC->SSP_PCLKREG, SSP_PCLKBIT) = 1; +void spi_preinit() +{ + /* Set clock prescaler to 1:1 */ + BITBAND( LPC_SC->SSP_PCLKREG, SSP_PCLKBIT ) = 1; } -void spi_init() { +void spi_init() +{ - /* configure data format - 8 bits, SPI, CPOL=0, CPHA=0, 1 clock per bit */ - SSP_REGS->CR0 = (8-1); + /* configure data format - 8 bits, SPI, CPOL=0, CPHA=0, 1 clock per bit */ + SSP_REGS->CR0 = ( 8 - 1 ); - /* set clock prescaler */ - SSP_REGS->CPSR = SSP_CLK_DIVISOR; + /* set clock prescaler */ + SSP_REGS->CPSR = SSP_CLK_DIVISOR; - /* Enable SSP */ - SSP_REGS->CR1 = BV(1); + /* Enable SSP */ + SSP_REGS->CR1 = BV( 1 ); - /* Enable DMA controller, little-endian mode */ - BITBAND(LPC_SC->PCONP, 29) = 1; - LPC_GPDMA->DMACConfig = 1; + /* Enable DMA controller, little-endian mode */ + BITBAND( LPC_SC->PCONP, 29 ) = 1; + LPC_GPDMA->DMACConfig = 1; } -void spi_tx_sync() { - /* Wait until TX fifo is flushed */ - while (BITBAND(SSP_REGS->SR, SSP_BSY)) ; +void spi_tx_sync() +{ + /* Wait until TX fifo is flushed */ + while ( BITBAND( SSP_REGS->SR, SSP_BSY ) ) ; } -void spi_tx_byte(uint8_t data) { - /* Wait until TX fifo can accept data */ - while (!BITBAND(SSP_REGS->SR, SSP_TNF)) ; +void spi_tx_byte( uint8_t data ) +{ + /* Wait until TX fifo can accept data */ + while ( !BITBAND( SSP_REGS->SR, SSP_TNF ) ) ; - /* Send byte */ - SSP_REGS->DR = data; + /* Send byte */ + SSP_REGS->DR = data; } -uint8_t spi_txrx_byte(uint8_t data) { - /* Wait until SSP is not busy */ - while (BITBAND(SSP_REGS->SR, SSP_BSY)) ; +uint8_t spi_txrx_byte( uint8_t data ) +{ + /* Wait until SSP is not busy */ + while ( BITBAND( SSP_REGS->SR, SSP_BSY ) ) ; - /* Clear RX fifo */ - while (BITBAND(SSP_REGS->SR, SSP_RNE)) - (void) SSP_REGS->DR; - - /* Transmit a single byte */ - SSP_REGS->DR = data; - - /* Wait until answer has been received */ - while (!BITBAND(SSP_REGS->SR, SSP_RNE)) ; - - return SSP_REGS->DR; -} - -uint8_t spi_rx_byte() { - /* Wait until SSP is not busy */ - while (BITBAND(SSP_REGS->SR, SSP_BSY)) ; - - /* Clear RX fifo */ - while (BITBAND(SSP_REGS->SR, SSP_RNE)) - (void) SSP_REGS->DR; - - /* Transmit a single dummy byte */ - SSP_REGS->DR = 0xff; - - /* Wait until answer has been received */ - while (!BITBAND(SSP_REGS->SR, SSP_RNE)) ; - - return SSP_REGS->DR; -} - -void spi_tx_block(const void *ptr, unsigned int length) { - const uint8_t *data = (const uint8_t *)ptr; - - while (length--) { - /* Wait until TX fifo can accept data */ - while (!BITBAND(SSP_REGS->SR, SSP_TNF)) ; - - SSP_REGS->DR = *data++; - } -} - -void spi_rx_block(void *ptr, unsigned int length) { - uint8_t *data = (uint8_t *)ptr; - unsigned int txlen = length; - - /* Wait until SSP is not busy */ - while (BITBAND(SSP_REGS->SR, SSP_BSY)) ; - - /* Clear RX fifo */ - while (BITBAND(SSP_REGS->SR, SSP_RNE)) - (void) SSP_REGS->DR; - - if ((length & 3) != 0 || ((uint32_t)ptr & 3) != 0) { - /* Odd length or unaligned buffer */ - while (length > 0) { - /* Wait until TX or RX FIFO are ready */ - while (txlen > 0 && !BITBAND(SSP_REGS->SR, SSP_TNF) && - !BITBAND(SSP_REGS->SR, SSP_RNE)) ; - - /* Try to receive data */ - while (length > 0 && BITBAND(SSP_REGS->SR, SSP_RNE)) { - *data++ = SSP_REGS->DR; - length--; - } - - /* Send dummy data until TX full or RX ready */ - while (txlen > 0 && BITBAND(SSP_REGS->SR, SSP_TNF) && !BITBAND(SSP_REGS->SR, SSP_RNE)) { - txlen--; - SSP_REGS->DR = 0xff; - } - } - } else { - /* Clear interrupt flags of DMA channels 0 */ - LPC_GPDMA->DMACIntTCClear = BV(0); - LPC_GPDMA->DMACIntErrClr = BV(0); - - /* Set up RX DMA channel */ - SSP_DMACH->DMACCSrcAddr = (uint32_t)&SSP_REGS->DR; - SSP_DMACH->DMACCDestAddr = (uint32_t)ptr; - SSP_DMACH->DMACCLLI = 0; // no linked list - SSP_DMACH->DMACCControl = length - | (0 << 12) // source burst size 1 (FIXME: Check if larger possible/useful) - | (0 << 15) // destination burst size 1 - | (0 << 18) // source transfer width 1 byte - | (2 << 21) // destination transfer width 4 bytes - | (0 << 26) // source address not incremented - | (1 << 27) // destination address incremented - ; - SSP_DMACH->DMACCConfig = 1 // enable channel - | (SSP_DMAID_RX << 1) // data source SSP RX - | (2 << 11) // transfer from peripheral to memory - ; - - /* Enable RX FIFO DMA */ - SSP_REGS->DMACR = 1; - - /* Write bytes into TX FIFO */ - // FIXME: Any value in doing this using DMA too? - while (txlen > 0) { - while (txlen > 0 && BITBAND(SSP_REGS->SR, SSP_TNF)) { - txlen--; - SSP_REGS->DR = 0xff; - } + /* Clear RX fifo */ + while ( BITBAND( SSP_REGS->SR, SSP_RNE ) ) + { + ( void ) SSP_REGS->DR; } - /* Wait until DMA channel disables itself */ - while (SSP_DMACH->DMACCConfig & 1) ; + /* Transmit a single byte */ + SSP_REGS->DR = data; - /* Disable RX FIFO DMA */ - SSP_REGS->DMACR = 0; - } + /* Wait until answer has been received */ + while ( !BITBAND( SSP_REGS->SR, SSP_RNE ) ) ; + + return SSP_REGS->DR; +} + +uint8_t spi_rx_byte() +{ + /* Wait until SSP is not busy */ + while ( BITBAND( SSP_REGS->SR, SSP_BSY ) ) ; + + /* Clear RX fifo */ + while ( BITBAND( SSP_REGS->SR, SSP_RNE ) ) + { + ( void ) SSP_REGS->DR; + } + + /* Transmit a single dummy byte */ + SSP_REGS->DR = 0xff; + + /* Wait until answer has been received */ + while ( !BITBAND( SSP_REGS->SR, SSP_RNE ) ) ; + + return SSP_REGS->DR; +} + +void spi_tx_block( const void *ptr, unsigned int length ) +{ + const uint8_t *data = ( const uint8_t * )ptr; + + while ( length-- ) + { + /* Wait until TX fifo can accept data */ + while ( !BITBAND( SSP_REGS->SR, SSP_TNF ) ) ; + + SSP_REGS->DR = *data++; + } +} + +void spi_rx_block( void *ptr, unsigned int length ) +{ + uint8_t *data = ( uint8_t * )ptr; + unsigned int txlen = length; + + /* Wait until SSP is not busy */ + while ( BITBAND( SSP_REGS->SR, SSP_BSY ) ) ; + + /* Clear RX fifo */ + while ( BITBAND( SSP_REGS->SR, SSP_RNE ) ) + { + ( void ) SSP_REGS->DR; + } + + if ( ( length & 3 ) != 0 || ( ( uint32_t )ptr & 3 ) != 0 ) + { + /* Odd length or unaligned buffer */ + while ( length > 0 ) + { + /* Wait until TX or RX FIFO are ready */ + while ( txlen > 0 && !BITBAND( SSP_REGS->SR, SSP_TNF ) && + !BITBAND( SSP_REGS->SR, SSP_RNE ) ) ; + + /* Try to receive data */ + while ( length > 0 && BITBAND( SSP_REGS->SR, SSP_RNE ) ) + { + *data++ = SSP_REGS->DR; + length--; + } + + /* Send dummy data until TX full or RX ready */ + while ( txlen > 0 && BITBAND( SSP_REGS->SR, SSP_TNF ) && !BITBAND( SSP_REGS->SR, SSP_RNE ) ) + { + txlen--; + SSP_REGS->DR = 0xff; + } + } + } + else + { + /* Clear interrupt flags of DMA channels 0 */ + LPC_GPDMA->DMACIntTCClear = BV( 0 ); + LPC_GPDMA->DMACIntErrClr = BV( 0 ); + + /* Set up RX DMA channel */ + SSP_DMACH->DMACCSrcAddr = ( uint32_t )&SSP_REGS->DR; + SSP_DMACH->DMACCDestAddr = ( uint32_t )ptr; + SSP_DMACH->DMACCLLI = 0; // no linked list + SSP_DMACH->DMACCControl = length + | ( 0 << 12 ) // source burst size 1 (FIXME: Check if larger possible/useful) + | ( 0 << 15 ) // destination burst size 1 + | ( 0 << 18 ) // source transfer width 1 byte + | ( 2 << 21 ) // destination transfer width 4 bytes + | ( 0 << 26 ) // source address not incremented + | ( 1 << 27 ) // destination address incremented + ; + SSP_DMACH->DMACCConfig = 1 // enable channel + | ( SSP_DMAID_RX << 1 ) // data source SSP RX + | ( 2 << 11 ) // transfer from peripheral to memory + ; + + /* Enable RX FIFO DMA */ + SSP_REGS->DMACR = 1; + + /* Write bytes into TX FIFO */ + // FIXME: Any value in doing this using DMA too? + while ( txlen > 0 ) + { + while ( txlen > 0 && BITBAND( SSP_REGS->SR, SSP_TNF ) ) + { + txlen--; + SSP_REGS->DR = 0xff; + } + } + + /* Wait until DMA channel disables itself */ + while ( SSP_DMACH->DMACCConfig & 1 ) ; + + /* Disable RX FIFO DMA */ + SSP_REGS->DMACR = 0; + } } diff --git a/src/spi.h b/src/spi.h index b90c092..a071fc6 100644 --- a/src/spi.h +++ b/src/spi.h @@ -39,27 +39,27 @@ typedef enum { SPI_SPEED_FAST, SPI_SPEED_SLOW, SPI_SPEED_FPGA_FAST, SPI_SPEED_FPGA_SLOW } spi_speed_t; /* Pre-Initialize SPI interface (PCLK divider before PLL setup) */ -void spi_preinit(void); +void spi_preinit( void ); /* Initialize SPI interface */ -void spi_init(void); +void spi_init( void ); /* Transmit a single byte */ -void spi_tx_byte(uint8_t data); +void spi_tx_byte( uint8_t data ); /* Transmit a single byte and return received data */ -uint8_t spi_txrx_byte(uint8_t data); +uint8_t spi_txrx_byte( uint8_t data ); /* Transmit a data block */ -void spi_tx_block(const void *data, unsigned int length); +void spi_tx_block( const void *data, unsigned int length ); /* Receive a single byte */ -uint8_t spi_rx_byte(void); +uint8_t spi_rx_byte( void ); /* Receive a data block */ -void spi_rx_block(void *data, unsigned int length); +void spi_rx_block( void *data, unsigned int length ); /* wait for SPI TX FIFO to become empty */ -void spi_tx_sync(void); +void spi_tx_sync( void ); #endif diff --git a/src/sysinfo.c b/src/sysinfo.c index 354f575..c9a8a96 100644 --- a/src/sysinfo.c +++ b/src/sysinfo.c @@ -18,110 +18,138 @@ static uint32_t sd_tacc_max, sd_tacc_avg; -void sysinfo_loop() { - sd_tacc_max = 0; - sd_tacc_avg = 0; - while(sram_readbyte(SRAM_CMD_ADDR) != 0x00) { - write_sysinfo(); - delay_ms(100); - } -} - -void write_sysinfo() { - uint32_t sram_addr = SRAM_SYSINFO_ADDR; - char linebuf[40]; - int len; - int sd_ok = 0; - uint8_t *sd_cid = sdn_getcid(); - uint32_t sd_tacc_max_int = sd_tacc_max / 1000; - uint32_t sd_tacc_max_frac = sd_tacc_max - (sd_tacc_max_int * 1000); - uint32_t sd_tacc_avg_int = sd_tacc_avg / 1000; - uint32_t sd_tacc_avg_frac = sd_tacc_avg - (sd_tacc_avg_int * 1000); - uint16_t numfiles = sram_readshort(SRAM_DB_ADDR+12); - uint16_t numdirs = sram_readshort(SRAM_DB_ADDR+14); - int32_t sysclk = get_snes_sysclk(); - - len = snprintf(linebuf, sizeof(linebuf), "Firmware version: %s", CONFIG_VERSION); - sram_writeblock(linebuf, sram_addr, 40); - sram_memset(sram_addr+len, 40-len, 0x20); - sram_addr += 40; - len = snprintf(linebuf, sizeof(linebuf), " "); - sram_writeblock(linebuf, sram_addr, 40); - sram_memset(sram_addr+len, 40-len, 0x20); - sram_addr += 40; - if(disk_state == DISK_REMOVED) { +void sysinfo_loop() +{ sd_tacc_max = 0; sd_tacc_avg = 0; - len = snprintf(linebuf, sizeof(linebuf), " "); - sram_writeblock(linebuf, sram_addr, 40); - sram_memset(sram_addr+len, 40-len, 0x20); - sram_addr += 40; - len = snprintf(linebuf, sizeof(linebuf), " *** SD Card removed *** "); - sram_writeblock(linebuf, sram_addr, 40); - sram_memset(sram_addr+len, 40-len, 0x20); - sram_addr += 40; - len = snprintf(linebuf, sizeof(linebuf), " "); - sram_writeblock(linebuf, sram_addr, 40); - sram_memset(sram_addr+len, 40-len, 0x20); - sram_addr += 40; - len = snprintf(linebuf, sizeof(linebuf), " "); - sram_writeblock(linebuf, sram_addr, 40); - sram_memset(sram_addr+len, 40-len, 0x20); - sram_addr += 40; - sd_ok = 0; - } else { - len = snprintf(linebuf, sizeof(linebuf), "SD Maker/OEM: 0x%02x, \"%c%c\"", sd_cid[1], sd_cid[2], sd_cid[3]); - sram_writeblock(linebuf, sram_addr, 40); - sram_memset(sram_addr+len, 40-len, 0x20); - sram_addr += 40; - len = snprintf(linebuf, sizeof(linebuf), "SD Product Name: \"%c%c%c%c%c\", Rev. %d.%d", sd_cid[4], sd_cid[5], sd_cid[6], sd_cid[7], sd_cid[8], sd_cid[9]>>4, sd_cid[9]&15); - sram_writeblock(linebuf, sram_addr, 40); - sram_memset(sram_addr+len, 40-len, 0x20); - sram_addr += 40; - len = snprintf(linebuf, sizeof(linebuf), "SD Serial No.: %02x%02x%02x%02x, Mfd. %d/%02d", sd_cid[10], sd_cid[11], sd_cid[12], sd_cid[13], 2000+((sd_cid[14]&15)<<4)+(sd_cid[15]>>4), sd_cid[15]&15); - sram_writeblock(linebuf, sram_addr, 40); - sram_memset(sram_addr+len, 40-len, 0x20); - sram_addr += 40; - if(sd_tacc_max) - len = snprintf(linebuf, sizeof(linebuf), "SD acc. time: %ld.%03ld / %ld.%03ld ms avg/max", sd_tacc_avg_int, sd_tacc_avg_frac, sd_tacc_max_int, sd_tacc_max_frac); - else - len = snprintf(linebuf, sizeof(linebuf), "SD acc. time: measuring... "); - sram_writeblock(linebuf, sram_addr, 40); - sram_memset(sram_addr+len, 40-len, 0x20); - sram_addr += 40; - sd_ok = 1; - } - len = snprintf(linebuf, sizeof(linebuf), " "); - sram_writeblock(linebuf, sram_addr, 40); - sram_memset(sram_addr+len, 40-len, 0x20); - sram_addr += 40; - len = snprintf(linebuf, sizeof(linebuf), "CIC state: %s", get_cic_statefriendlyname(get_cic_state())); - sram_writeblock(linebuf, sram_addr, 40); - sram_memset(sram_addr+len, 40-len, 0x20); - sram_addr += 40; - if(sysclk == -1) - len = snprintf(linebuf, sizeof(linebuf), "SNES master clock: measuring..."); - else - len = snprintf(linebuf, sizeof(linebuf), "SNES master clock: %ldHz ", get_snes_sysclk()); - sram_writeblock(linebuf, sram_addr, 40); - sram_memset(sram_addr+len, 40-len, 0x20); - sram_addr += 40; - len = snprintf(linebuf, sizeof(linebuf), " "); - sram_writeblock(linebuf, sram_addr, 40); - sram_memset(sram_addr+len, 40-len, 0x20); - sram_addr += 40; - len = snprintf(linebuf, sizeof(linebuf), "Database: %d files, %d dirs", numfiles, numdirs); - sram_writeblock(linebuf, sram_addr, 40); - sram_memset(sram_addr+len, 40-len, 0x20); - sram_addr += 40; - len = snprintf(linebuf, sizeof(linebuf), " "); - sram_writeblock(linebuf, sram_addr, 40); - sram_memset(sram_addr+len, 40-len, 0x20); - sram_addr += 40; - len = snprintf(linebuf, sizeof(linebuf), " "); - sram_writeblock(linebuf, sram_addr, 40); - sram_memset(sram_addr+len, 40-len, 0x20); - sram_hexdump(SRAM_SYSINFO_ADDR, 13*40); - if(sysclk != -1 && sd_ok)sdn_gettacc(&sd_tacc_max, &sd_tacc_avg); + + while ( sram_readbyte( SRAM_CMD_ADDR ) != 0x00 ) + { + write_sysinfo(); + delay_ms( 100 ); + } +} + +void write_sysinfo() +{ + uint32_t sram_addr = SRAM_SYSINFO_ADDR; + char linebuf[40]; + int len; + int sd_ok = 0; + uint8_t *sd_cid = sdn_getcid(); + uint32_t sd_tacc_max_int = sd_tacc_max / 1000; + uint32_t sd_tacc_max_frac = sd_tacc_max - ( sd_tacc_max_int * 1000 ); + uint32_t sd_tacc_avg_int = sd_tacc_avg / 1000; + uint32_t sd_tacc_avg_frac = sd_tacc_avg - ( sd_tacc_avg_int * 1000 ); + uint16_t numfiles = sram_readshort( SRAM_DB_ADDR + 12 ); + uint16_t numdirs = sram_readshort( SRAM_DB_ADDR + 14 ); + int32_t sysclk = get_snes_sysclk(); + + len = snprintf( linebuf, sizeof( linebuf ), "Firmware version: %s", CONFIG_VERSION ); + sram_writeblock( linebuf, sram_addr, 40 ); + sram_memset( sram_addr + len, 40 - len, 0x20 ); + sram_addr += 40; + len = snprintf( linebuf, sizeof( linebuf ), " " ); + sram_writeblock( linebuf, sram_addr, 40 ); + sram_memset( sram_addr + len, 40 - len, 0x20 ); + sram_addr += 40; + + if ( disk_state == DISK_REMOVED ) + { + sd_tacc_max = 0; + sd_tacc_avg = 0; + len = snprintf( linebuf, sizeof( linebuf ), " " ); + sram_writeblock( linebuf, sram_addr, 40 ); + sram_memset( sram_addr + len, 40 - len, 0x20 ); + sram_addr += 40; + len = snprintf( linebuf, sizeof( linebuf ), " *** SD Card removed *** " ); + sram_writeblock( linebuf, sram_addr, 40 ); + sram_memset( sram_addr + len, 40 - len, 0x20 ); + sram_addr += 40; + len = snprintf( linebuf, sizeof( linebuf ), " " ); + sram_writeblock( linebuf, sram_addr, 40 ); + sram_memset( sram_addr + len, 40 - len, 0x20 ); + sram_addr += 40; + len = snprintf( linebuf, sizeof( linebuf ), " " ); + sram_writeblock( linebuf, sram_addr, 40 ); + sram_memset( sram_addr + len, 40 - len, 0x20 ); + sram_addr += 40; + sd_ok = 0; + } + else + { + len = snprintf( linebuf, sizeof( linebuf ), "SD Maker/OEM: 0x%02x, \"%c%c\"", sd_cid[1], sd_cid[2], sd_cid[3] ); + sram_writeblock( linebuf, sram_addr, 40 ); + sram_memset( sram_addr + len, 40 - len, 0x20 ); + sram_addr += 40; + len = snprintf( linebuf, sizeof( linebuf ), "SD Product Name: \"%c%c%c%c%c\", Rev. %d.%d", sd_cid[4], sd_cid[5], + sd_cid[6], sd_cid[7], sd_cid[8], sd_cid[9] >> 4, sd_cid[9] & 15 ); + sram_writeblock( linebuf, sram_addr, 40 ); + sram_memset( sram_addr + len, 40 - len, 0x20 ); + sram_addr += 40; + len = snprintf( linebuf, sizeof( linebuf ), "SD Serial No.: %02x%02x%02x%02x, Mfd. %d/%02d", sd_cid[10], sd_cid[11], + sd_cid[12], sd_cid[13], 2000 + ( ( sd_cid[14] & 15 ) << 4 ) + ( sd_cid[15] >> 4 ), sd_cid[15] & 15 ); + sram_writeblock( linebuf, sram_addr, 40 ); + sram_memset( sram_addr + len, 40 - len, 0x20 ); + sram_addr += 40; + + if ( sd_tacc_max ) + { + len = snprintf( linebuf, sizeof( linebuf ), "SD acc. time: %ld.%03ld / %ld.%03ld ms avg/max", sd_tacc_avg_int, + sd_tacc_avg_frac, sd_tacc_max_int, sd_tacc_max_frac ); + } + else + { + len = snprintf( linebuf, sizeof( linebuf ), "SD acc. time: measuring... " ); + } + + sram_writeblock( linebuf, sram_addr, 40 ); + sram_memset( sram_addr + len, 40 - len, 0x20 ); + sram_addr += 40; + sd_ok = 1; + } + + len = snprintf( linebuf, sizeof( linebuf ), " " ); + sram_writeblock( linebuf, sram_addr, 40 ); + sram_memset( sram_addr + len, 40 - len, 0x20 ); + sram_addr += 40; + len = snprintf( linebuf, sizeof( linebuf ), "CIC state: %s", get_cic_statefriendlyname( get_cic_state() ) ); + sram_writeblock( linebuf, sram_addr, 40 ); + sram_memset( sram_addr + len, 40 - len, 0x20 ); + sram_addr += 40; + + if ( sysclk == -1 ) + { + len = snprintf( linebuf, sizeof( linebuf ), "SNES master clock: measuring..." ); + } + else + { + len = snprintf( linebuf, sizeof( linebuf ), "SNES master clock: %ldHz ", get_snes_sysclk() ); + } + + sram_writeblock( linebuf, sram_addr, 40 ); + sram_memset( sram_addr + len, 40 - len, 0x20 ); + sram_addr += 40; + len = snprintf( linebuf, sizeof( linebuf ), " " ); + sram_writeblock( linebuf, sram_addr, 40 ); + sram_memset( sram_addr + len, 40 - len, 0x20 ); + sram_addr += 40; + len = snprintf( linebuf, sizeof( linebuf ), "Database: %d files, %d dirs", numfiles, numdirs ); + sram_writeblock( linebuf, sram_addr, 40 ); + sram_memset( sram_addr + len, 40 - len, 0x20 ); + sram_addr += 40; + len = snprintf( linebuf, sizeof( linebuf ), " " ); + sram_writeblock( linebuf, sram_addr, 40 ); + sram_memset( sram_addr + len, 40 - len, 0x20 ); + sram_addr += 40; + len = snprintf( linebuf, sizeof( linebuf ), " " ); + sram_writeblock( linebuf, sram_addr, 40 ); + sram_memset( sram_addr + len, 40 - len, 0x20 ); + sram_hexdump( SRAM_SYSINFO_ADDR, 13 * 40 ); + + if ( sysclk != -1 && sd_ok ) + { + sdn_gettacc( &sd_tacc_max, &sd_tacc_avg ); + } } diff --git a/src/tests.h b/src/tests.h index aeff6f3..efa2dd8 100644 --- a/src/tests.h +++ b/src/tests.h @@ -7,5 +7,6 @@ void test_sdbench_local(char *filename); void test_rom_rw(void); void test_fpga_echo(void); +int test_mem(void); #endif diff --git a/src/tests/main.c b/src/tests/main.c index 25ba103..4381da7 100644 --- a/src/tests/main.c +++ b/src/tests/main.c @@ -99,11 +99,11 @@ led_pwm(); NO_RUN, NO_RUN, NO_RUN, NO_RUN, NO_RUN, NO_RUN }; - testresults[TEST_SD] = test_sd(); + testresults[TEST_SD] = test_sd(); //testresults[TEST_USB] = test_usb(); - testresults[TEST_RTC] = test_rtc(); + //testresults[TEST_RTC] = test_rtc(); delay_ms(209); - testresults[TEST_CIC] = test_cic(); +// testresults[TEST_CIC] = test_cic(); testresults[TEST_FPGA] = test_fpga(); testresults[TEST_RAM] = test_mem(); printf("Loading SNES test ROM\n=====================\n"); diff --git a/src/tests/timer.c b/src/tests/timer.c index d6012ae..4bd0aa6 100644 --- a/src/tests/timer.c +++ b/src/tests/timer.c @@ -73,7 +73,8 @@ void RIT_IRQHandler(void) { RIT_Hook(); } -void timer_init(void) { +void timer_init(void) +{ /* turn on power to RIT */ BITBAND(LPC_SC->PCONP, PCRIT) = 1; @@ -87,7 +88,8 @@ void timer_init(void) { SysTick_Config((SysTick->CALIB & SysTick_CALIB_TENMS_Msk)); } -void delay_us(unsigned int time) { +void delay_us(unsigned int time) +{ /* Prepare RIT */ LPC_RIT->RICOUNTER = 0; LPC_RIT->RICOMPVAL = (CONFIG_CPU_FREQUENCY / 1000000) * time; diff --git a/src/timer.c b/src/timer.c index 30d6e94..363bb5c 100644 --- a/src/timer.c +++ b/src/timer.c @@ -18,101 +18,117 @@ extern volatile int reset_pressed; volatile tick_t ticks; volatile int wokefromrit; -void __attribute__((weak,noinline)) SysTick_Hook(void) { - /* Empty function for hooking the systick handler */ +void __attribute__( ( weak, noinline ) ) SysTick_Hook( void ) +{ + /* Empty function for hooking the systick handler */ } /* Systick interrupt handler */ -void SysTick_Handler(void) { - ticks++; - static uint16_t sdch_state = 0; - static uint16_t reset_state = 0; - sdch_state = (sdch_state << 1) | SDCARD_DETECT | 0xe000; - if((sdch_state == 0xf000) || (sdch_state == 0xefff)) { - sd_changed = 1; - } - reset_state = (reset_state << 1) | get_snes_reset() | 0xe000; - if((reset_state == 0xf000) || (reset_state == 0xefff)) { - reset_pressed = (reset_state == 0xf000); - reset_changed = 1; - } - sdn_changed(); - SysTick_Hook(); +void SysTick_Handler( void ) +{ + ticks++; + static uint16_t sdch_state = 0; + static uint16_t reset_state = 0; + sdch_state = ( sdch_state << 1 ) | SDCARD_DETECT | 0xe000; + + if ( ( sdch_state == 0xf000 ) || ( sdch_state == 0xefff ) ) + { + sd_changed = 1; + } + + reset_state = ( reset_state << 1 ) | get_snes_reset() | 0xe000; + + if ( ( reset_state == 0xf000 ) || ( reset_state == 0xefff ) ) + { + reset_pressed = ( reset_state == 0xf000 ); + reset_changed = 1; + } + + sdn_changed(); + SysTick_Hook(); } -void __attribute__((weak,noinline)) RIT_Hook(void) { +void __attribute__( ( weak, noinline ) ) RIT_Hook( void ) +{ } -void RIT_IRQHandler(void) { - LPC_RIT->RICTRL = BV(RITINT); - NVIC_ClearPendingIRQ(RIT_IRQn); - wokefromrit = 1; - RIT_Hook(); +void RIT_IRQHandler( void ) +{ + LPC_RIT->RICTRL = BV( RITINT ); + NVIC_ClearPendingIRQ( RIT_IRQn ); + wokefromrit = 1; + RIT_Hook(); } -void timer_init(void) { - /* turn on power to RIT */ - BITBAND(LPC_SC->PCONP, PCRIT) = 1; +void timer_init( void ) +{ + /* turn on power to RIT */ + BITBAND( LPC_SC->PCONP, PCRIT ) = 1; - /* clear RIT mask */ - LPC_RIT->RIMASK = 0; /*xffffffff;*/ + /* clear RIT mask */ + LPC_RIT->RIMASK = 0; /*xffffffff;*/ - /* PCLK_RIT = CCLK */ - BITBAND(LPC_SC->PCLKSEL1, 27) = 0; - BITBAND(LPC_SC->PCLKSEL1, 26) = 1; + /* PCLK_RIT = CCLK */ + BITBAND( LPC_SC->PCLKSEL1, 27 ) = 0; + BITBAND( LPC_SC->PCLKSEL1, 26 ) = 1; - /* PCLK_TIMER3 = CCLK/4 */ - BITBAND(LPC_SC->PCLKSEL1, 15) = 0; - BITBAND(LPC_SC->PCLKSEL1, 14) = 0; + /* PCLK_TIMER3 = CCLK/4 */ + BITBAND( LPC_SC->PCLKSEL1, 15 ) = 0; + BITBAND( LPC_SC->PCLKSEL1, 14 ) = 0; - /* enable timer 3 */ - BITBAND(LPC_SC->PCLKSEL1, PCLK_TIMER3) = 1; + /* enable timer 3 */ + BITBAND( LPC_SC->PCLKSEL1, PCLK_TIMER3 ) = 1; - /* enable SysTick */ - SysTick_Config((SysTick->CALIB & SysTick_CALIB_TENMS_Msk)); + /* enable SysTick */ + SysTick_Config( ( SysTick->CALIB & SysTick_CALIB_TENMS_Msk ) ); } -void delay_us(unsigned int time) { - /* Prepare RIT */ - LPC_RIT->RICOUNTER = 0; - LPC_RIT->RICOMPVAL = (CONFIG_CPU_FREQUENCY / 1000000) * time; - LPC_RIT->RICTRL = BV(RITEN) | BV(RITINT); +void delay_us( unsigned int time ) +{ + /* Prepare RIT */ + LPC_RIT->RICOUNTER = 0; + LPC_RIT->RICOMPVAL = ( CONFIG_CPU_FREQUENCY / 1000000 ) * time; + LPC_RIT->RICTRL = BV( RITEN ) | BV( RITINT ); - /* Wait until RIT signals an interrupt */ - while (!(BITBAND(LPC_RIT->RICTRL, RITINT))) ; + /* Wait until RIT signals an interrupt */ + while ( !( BITBAND( LPC_RIT->RICTRL, RITINT ) ) ) ; - /* Disable RIT */ - LPC_RIT->RICTRL = 0; + /* Disable RIT */ + LPC_RIT->RICTRL = 0; } -void delay_ms(unsigned int time) { - /* Prepare RIT */ - LPC_RIT->RICOUNTER = 0; - LPC_RIT->RICOMPVAL = (CONFIG_CPU_FREQUENCY / 1000) * time; - LPC_RIT->RICTRL = BV(RITEN) | BV(RITINT); +void delay_ms( unsigned int time ) +{ + /* Prepare RIT */ + LPC_RIT->RICOUNTER = 0; + LPC_RIT->RICOMPVAL = ( CONFIG_CPU_FREQUENCY / 1000 ) * time; + LPC_RIT->RICTRL = BV( RITEN ) | BV( RITINT ); - /* Wait until RIT signals an interrupt */ - while (!(BITBAND(LPC_RIT->RICTRL, RITINT))) ; + /* Wait until RIT signals an interrupt */ + while ( !( BITBAND( LPC_RIT->RICTRL, RITINT ) ) ) ; - /* Disable RIT */ - LPC_RIT->RICTRL = 0; + /* Disable RIT */ + LPC_RIT->RICTRL = 0; } -void sleep_ms(unsigned int time) { +void sleep_ms( unsigned int time ) +{ - wokefromrit = 0; - /* Prepare RIT */ - LPC_RIT->RICOUNTER = 0; - LPC_RIT->RICOMPVAL = (CONFIG_CPU_FREQUENCY / 1000) * time; - LPC_RIT->RICTRL = BV(RITEN) | BV(RITINT); - NVIC_EnableIRQ(RIT_IRQn); + wokefromrit = 0; + /* Prepare RIT */ + LPC_RIT->RICOUNTER = 0; + LPC_RIT->RICOMPVAL = ( CONFIG_CPU_FREQUENCY / 1000 ) * time; + LPC_RIT->RICTRL = BV( RITEN ) | BV( RITINT ); + NVIC_EnableIRQ( RIT_IRQn ); - /* Wait until RIT signals an interrupt */ -//uart_putc(';'); - while(!wokefromrit) { - __WFI(); - } - NVIC_DisableIRQ(RIT_IRQn); - /* Disable RIT */ - LPC_RIT->RICTRL = BV(RITINT); + /* Wait until RIT signals an interrupt */ + //uart_putc(';'); + while ( !wokefromrit ) + { + __WFI(); + } + + NVIC_DisableIRQ( RIT_IRQn ); + /* Disable RIT */ + LPC_RIT->RICTRL = BV( RITINT ); } diff --git a/src/uart.c b/src/uart.c index 7677d78..2f26cd4 100644 --- a/src/uart.c +++ b/src/uart.c @@ -42,249 +42,334 @@ #else # error CONFIG_UART_NUM is not set or has an invalid value! #endif -static uint8_t uart_lookupratio(float f_fr) { - uint16_t errors[72]={0,67,71,77,83,91,100,111,125, - 133,143,154,167,182,200,214,222,231, - 250,267,273,286,300,308,333,357,364, - 375,385,400,417,429,444,455,462,467, - 500,533,538,545,556,571,583,600,615, - 625,636,643,667,692,700,714,727,733, - 750,769,778,786,800,818,833,846,857, - 867,875,889,900,909,917,923,929,933}; +static uint8_t uart_lookupratio( float f_fr ) +{ + uint16_t errors[72] = {0, 67, 71, 77, 83, 91, 100, 111, 125, + 133, 143, 154, 167, 182, 200, 214, 222, 231, + 250, 267, 273, 286, 300, 308, 333, 357, 364, + 375, 385, 400, 417, 429, 444, 455, 462, 467, + 500, 533, 538, 545, 556, 571, 583, 600, 615, + 625, 636, 643, 667, 692, 700, 714, 727, 733, + 750, 769, 778, 786, 800, 818, 833, 846, 857, + 867, 875, 889, 900, 909, 917, 923, 929, 933 + }; - uint8_t ratios[72]={0x10,0xf1,0xe1,0xd1,0xc1,0xb1,0xa1,0x91,0x81, - 0xf2,0x71,0xd2,0x61,0xb2,0x51,0xe3,0x92,0xd3, - 0x41,0xf4,0xb3,0x72,0xa3,0xd4,0x31,0xe5,0xb4, - 0x83,0xd5,0x52,0xc5,0x73,0x94,0xb5,0xd6,0xf7, - 0x21,0xf8,0xd7,0xb6,0x95,0x74,0xc7,0x53,0xd8, - 0x85,0xb7,0xe9,0x32,0xd9,0xa7,0x75,0xb8,0xfb, - 0x43,0xda,0x97,0xeb,0x54,0xb9,0x65,0xdb,0x76, - 0xfd,0x87,0x98,0xa9,0xba,0xcb,0xdc,0xed,0xfe}; + uint8_t ratios[72] = {0x10, 0xf1, 0xe1, 0xd1, 0xc1, 0xb1, 0xa1, 0x91, 0x81, + 0xf2, 0x71, 0xd2, 0x61, 0xb2, 0x51, 0xe3, 0x92, 0xd3, + 0x41, 0xf4, 0xb3, 0x72, 0xa3, 0xd4, 0x31, 0xe5, 0xb4, + 0x83, 0xd5, 0x52, 0xc5, 0x73, 0x94, 0xb5, 0xd6, 0xf7, + 0x21, 0xf8, 0xd7, 0xb6, 0x95, 0x74, 0xc7, 0x53, 0xd8, + 0x85, 0xb7, 0xe9, 0x32, 0xd9, 0xa7, 0x75, 0xb8, 0xfb, + 0x43, 0xda, 0x97, 0xeb, 0x54, 0xb9, 0x65, 0xdb, 0x76, + 0xfd, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe + }; - int fr = (f_fr-1)*1000; - int i=0, i_result=0; - int err=0, lasterr=1000; - for(i=0; i<72; i++) { - if(fr990) { - int_ratio++; - } else if(error>10) { - f_fr=1.5; - f_dl=f_pclk / (16 * baudrate * (f_fr)); - dl = (int)f_dl; - f_fr=f_pclk / (16 * baudrate * dl); - fract_ratio = uart_lookupratio(f_fr); - } - if(!dl) { - return int_ratio; - } else { - return ((fract_ratio<<16)&0xff0000) | dl; - } +static uint32_t baud2divisor( unsigned int baudrate ) +{ + uint32_t int_ratio; + uint32_t error; + uint32_t dl = 0; + float f_ratio; + float f_fr; + float f_dl; + float f_pclk = ( float )CONFIG_CPU_FREQUENCY / CONFIG_UART_PCLKDIV; + uint8_t fract_ratio; + f_ratio = ( f_pclk / 16 / baudrate ); + int_ratio = ( int )f_ratio; + error = ( f_ratio * 1000 ) - ( int_ratio * 1000 ); + + if ( error > 990 ) + { + int_ratio++; + } + else if ( error > 10 ) + { + f_fr = 1.5; + f_dl = f_pclk / ( 16 * baudrate * ( f_fr ) ); + dl = ( int )f_dl; + f_fr = f_pclk / ( 16 * baudrate * dl ); + fract_ratio = uart_lookupratio( f_fr ); + } + + if ( !dl ) + { + return int_ratio; + } + else + { + return ( ( fract_ratio << 16 ) & 0xff0000 ) | dl; + } } static char txbuf[1 << CONFIG_UART_TX_BUF_SHIFT]; -static volatile unsigned int read_idx,write_idx; +static volatile unsigned int read_idx, write_idx; -void UART_HANDLER(void) { - int iir = UART_REGS->IIR; - if (!(iir & 1)) { - /* Interrupt is pending */ - switch (iir & 14) { +void UART_HANDLER( void ) +{ + int iir = UART_REGS->IIR; + + if ( !( iir & 1 ) ) + { + /* Interrupt is pending */ + switch ( iir & 14 ) + { #if CONFIG_UART_NUM == 1 - case 0: /* modem status */ - (void) UART_REGS->MSR; // dummy read to clear - break; + + case 0: /* modem status */ + ( void ) UART_REGS->MSR; // dummy read to clear + break; #endif - case 2: /* THR empty - send */ - if (read_idx != write_idx) { - int maxchars = 16; - while (read_idx != write_idx && --maxchars > 0) { - UART_REGS->THR = (unsigned char)txbuf[read_idx]; - read_idx = (read_idx+1) & (sizeof(txbuf)-1); - } - if (read_idx == write_idx) { - /* buffer empty - turn off THRE interrupt */ - BITBAND(UART_REGS->IER, 1) = 0; - } - } - break; - - case 12: /* RX timeout */ - case 4: /* data received - not implemented yet */ - (void) UART_REGS->RBR; // dummy read to clear - break; + case 2: /* THR empty - send */ + if ( read_idx != write_idx ) + { + int maxchars = 16; - case 6: /* RX error */ - (void) UART_REGS->LSR; // dummy read to clear + while ( read_idx != write_idx && --maxchars > 0 ) + { + UART_REGS->THR = ( unsigned char )txbuf[read_idx]; + read_idx = ( read_idx + 1 ) & ( sizeof( txbuf ) - 1 ); + } - default: break; + if ( read_idx == write_idx ) + { + /* buffer empty - turn off THRE interrupt */ + BITBAND( UART_REGS->IER, 1 ) = 0; + } + } + + break; + + case 12: /* RX timeout */ + case 4: /* data received - not implemented yet */ + ( void ) UART_REGS->RBR; // dummy read to clear + break; + + case 6: /* RX error */ + ( void ) UART_REGS->LSR; // dummy read to clear + + default: break; + } } - } } -void uart_putc(char c) { - if (c == '\n') - uart_putc('\r'); +void uart_putc( char c ) +{ + if ( c == '\n' ) + { + uart_putc( '\r' ); + } - unsigned int tmp = (write_idx+1) & (sizeof(txbuf)-1) ; + unsigned int tmp = ( write_idx + 1 ) & ( sizeof( txbuf ) - 1 ) ; - if (read_idx == write_idx && (BITBAND(UART_REGS->LSR, 5))) { - /* buffer empty, THR empty -> send immediately */ - UART_REGS->THR = (unsigned char)c; - } else { + if ( read_idx == write_idx && ( BITBAND( UART_REGS->LSR, 5 ) ) ) + { + /* buffer empty, THR empty -> send immediately */ + UART_REGS->THR = ( unsigned char )c; + } + else + { #ifdef CONFIG_UART_DEADLOCKABLE - while (tmp == read_idx) ; + + while ( tmp == read_idx ) ; + #endif - BITBAND(UART_REGS->IER, 1) = 0; // turn off UART interrupt - txbuf[write_idx] = c; - write_idx = tmp; - BITBAND(UART_REGS->IER, 1) = 1; - } + BITBAND( UART_REGS->IER, 1 ) = 0; // turn off UART interrupt + txbuf[write_idx] = c; + write_idx = tmp; + BITBAND( UART_REGS->IER, 1 ) = 1; + } } /* Polling version only */ -unsigned char uart_getc(void) { - /* wait for character */ - while (!(BITBAND(UART_REGS->LSR, 0))) ; - return UART_REGS->RBR; +unsigned char uart_getc( void ) +{ + /* wait for character */ + while ( !( BITBAND( UART_REGS->LSR, 0 ) ) ) ; + + return UART_REGS->RBR; } /* Returns true if a char is ready */ -unsigned char uart_gotc(void) { - return BITBAND(UART_REGS->LSR, 0); +unsigned char uart_gotc( void ) +{ + return BITBAND( UART_REGS->LSR, 0 ); } -void uart_init(void) { - uint32_t div; +void uart_init( void ) +{ + uint32_t div; - /* Turn on power to UART */ - BITBAND(LPC_SC->PCONP, UART_PCONBIT) = 1; + /* Turn on power to UART */ + BITBAND( LPC_SC->PCONP, UART_PCONBIT ) = 1; - /* UART clock = CPU clock - this block is reduced at compile-time */ - if (CONFIG_UART_PCLKDIV == 1) { - BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1; - BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 0; - } else if (CONFIG_UART_PCLKDIV == 2) { - BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0; - BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 1; - } else if (CONFIG_UART_PCLKDIV == 4) { - BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0; - BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 0; - } else { // Fallback: Divide by 8 - BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1; - BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 1; - } + /* UART clock = CPU clock - this block is reduced at compile-time */ + if ( CONFIG_UART_PCLKDIV == 1 ) + { + BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1; + BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 0; + } + else if ( CONFIG_UART_PCLKDIV == 2 ) + { + BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0; + BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 1; + } + else if ( CONFIG_UART_PCLKDIV == 4 ) + { + BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0; + BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 0; + } + else // Fallback: Divide by 8 + { + BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1; + BITBAND( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 1; + } - /* set baud rate - no fractional stuff for now */ - UART_REGS->LCR = BV(7) | 3; // always 8n1 - div = baud2divisor(CONFIG_UART_BAUDRATE); + /* set baud rate - no fractional stuff for now */ + UART_REGS->LCR = BV( 7 ) | 3; // always 8n1 + div = baud2divisor( CONFIG_UART_BAUDRATE ); - UART_REGS->DLL = div & 0xff; - UART_REGS->DLM = (div >> 8) & 0xff; - BITBAND(UART_REGS->LCR, 7) = 0; + UART_REGS->DLL = div & 0xff; + UART_REGS->DLM = ( div >> 8 ) & 0xff; + BITBAND( UART_REGS->LCR, 7 ) = 0; - if (div & 0xff0000) { - UART_REGS->FDR = (div >> 16) & 0xff; - } + if ( div & 0xff0000 ) + { + UART_REGS->FDR = ( div >> 16 ) & 0xff; + } - /* reset and enable FIFO */ - UART_REGS->FCR = BV(0); + /* reset and enable FIFO */ + UART_REGS->FCR = BV( 0 ); - /* enable transmit interrupt */ - BITBAND(UART_REGS->IER, 1) = 1; - NVIC_EnableIRQ(UART_IRQ); + /* enable transmit interrupt */ + BITBAND( UART_REGS->IER, 1 ) = 1; + NVIC_EnableIRQ( UART_IRQ ); - UART_REGS->THR = '?'; + UART_REGS->THR = '?'; } /* --- generic code below --- */ -void uart_puthex(uint8_t num) { - uint8_t tmp; - tmp = (num & 0xf0) >> 4; - if (tmp < 10) - uart_putc('0'+tmp); - else - uart_putc('a'+tmp-10); +void uart_puthex( uint8_t num ) +{ + uint8_t tmp; + tmp = ( num & 0xf0 ) >> 4; - tmp = num & 0x0f; - if (tmp < 10) - uart_putc('0'+tmp); - else - uart_putc('a'+tmp-10); -} - -void uart_trace(void *ptr, uint16_t start, uint16_t len, uint32_t addr) { - uint16_t i; - uint8_t j; - uint8_t ch; - uint8_t *data = ptr; - - data+=start; - for(i=0;i>16); - uart_puthex(((addr + start)>>8) & 0xff); - uart_puthex((addr + start)&0xff); - uart_putc('|'); - uart_putc(' '); - for(j=0;j<16;j++) { - if(i+j0x7e) - ch='.'; - uart_putc(ch); - } else { - uart_putc(' '); - } + else + { + uart_putc( 'a' + tmp - 10 ); + } + + tmp = num & 0x0f; + + if ( tmp < 10 ) + { + uart_putc( '0' + tmp ); + } + else + { + uart_putc( 'a' + tmp - 10 ); } - uart_putc('|'); - uart_putcrlf(); - start+=16; - } } -void uart_flush(void) { - while (read_idx != write_idx) ; +void uart_trace( void *ptr, uint16_t start, uint16_t len, uint32_t addr ) +{ + uint16_t i; + uint8_t j; + uint8_t ch; + uint8_t *data = ptr; + + data += start; + + for ( i = 0; i < len; i += 16 ) + { + + uart_puthex( ( addr + start ) >> 16 ); + uart_puthex( ( ( addr + start ) >> 8 ) & 0xff ); + uart_puthex( ( addr + start ) & 0xff ); + uart_putc( '|' ); + uart_putc( ' ' ); + + for ( j = 0; j < 16; j++ ) + { + if ( i + j < len ) + { + ch = *( data + j ); + uart_puthex( ch ); + } + else + { + uart_putc( ' ' ); + uart_putc( ' ' ); + } + + uart_putc( ' ' ); + } + + uart_putc( '|' ); + + for ( j = 0; j < 16; j++ ) + { + if ( i + j < len ) + { + ch = *( data++ ); + + if ( ch < 32 || ch > 0x7e ) + { + ch = '.'; + } + + uart_putc( ch ); + } + else + { + uart_putc( ' ' ); + } + } + + uart_putc( '|' ); + uart_putcrlf(); + start += 16; + } } -void uart_puts(const char *text) { - while (*text) { - uart_putc(*text++); - } +void uart_flush( void ) +{ + while ( read_idx != write_idx ) ; +} + +void uart_puts( const char *text ) +{ + while ( *text ) + { + uart_putc( *text++ ); + } } diff --git a/src/uncfgware.c b/src/uncfgware.c index 145f97e..1a8167a 100644 --- a/src/uncfgware.c +++ b/src/uncfgware.c @@ -3,12 +3,14 @@ #include #include "cfgware.h" -int main(int argc, char *argv[]) +int main( int argc, char *argv[] ) { - int i; - for (i = 0; i < sizeof(cfgware); i++) - { - printf("%c", cfgware[i]); - } - return 0; + int i; + + for ( i = 0; i < sizeof( cfgware ); i++ ) + { + printf( "%c", cfgware[i] ); + } + + return 0; } diff --git a/src/utils/bin2h.c b/src/utils/bin2h.c index 612db24..a1853a5 100644 --- a/src/utils/bin2h.c +++ b/src/utils/bin2h.c @@ -1,49 +1,77 @@ #include #include -int main(int argc, char *argv[]) +int main( int argc, char *argv[] ) { - char var_name[30] = "cfgware"; - FILE *fpIn = NULL, *fpOut = NULL; - unsigned char buffer[5], i; - if ( argc == 3 ) - { - fpIn = fopen(argv[1], "rb"); - fpOut = fopen(argv[2], "wt"); - } - else if (argc == 2) - { - fpIn = fopen(argv[1], "rb"); - fpOut = stdout; - } - else if ( argc == 1 ) - { - fpIn = stdin; - fpOut = stdout; - } - else - { - fprintf(stderr, "usage: %s [infile] [outfile]\n", argv[0]); - return -1; - } - -// if (argc > 1) -// sprintf() + char var_name[30] = "cfgware"; + FILE *fpIn = NULL, *fpOut = NULL; + unsigned char buffer[5], i; + printf( "argc: %d\n", argc ); - if (fpIn == NULL) { fprintf(stderr, "Can't open '%s`: Aborting.", argv[1]); return -1; } - if (fpOut == NULL) { fprintf(stderr, "Can't open '%s`: Aborting.", argv[2]); return -1; } - - fprintf(fpOut, "const uint8_t %s[] = {\n", var_name); - i = 0; - while(!feof(fpIn)) - { - fread(buffer, 1, 1, fpIn); - fprintf(fpOut, "0x%02X, ", buffer[0]); - i++; if (i > 8) { fprintf(fpOut, "\n"); i = 0; } - } - if (i > 0) - fprintf(fpOut, "\n"); - fprintf(fpOut, "};"); - fclose(fpOut); fclose(fpIn); - return 0; + if ( argc == 4 ) + { + fpIn = fopen( argv[1], "rb" ); + fpOut = fopen( argv[2], "wt" ); + sprintf( var_name, "%s", argv[3] ); + } + else if ( argc == 3 ) + { + fpIn = fopen( argv[1], "rb" ); + fpOut = fopen( argv[2], "wt" ); + } + else if ( argc == 2 ) + { + fpIn = fopen( argv[1], "rb" ); + fpOut = stdout; + } + else if ( argc == 1 ) + { + fpIn = stdin; + fpOut = stdout; + } + else + { + fprintf( stderr, "usage: %s [infile] [outfile] [name]\n", argv[0] ); + return -1; + } + + // if (argc > 1) + // sprintf() + + if ( fpIn == NULL ) + { + fprintf( stderr, "Can't open '%s`: Aborting.", argv[1] ); + return -1; + } + + if ( fpOut == NULL ) + { + fprintf( stderr, "Can't open '%s`: Aborting.", argv[2] ); + return -1; + } + + fprintf( fpOut, "const uint8_t %s[] = {\n", var_name ); + i = 0; + + while ( !feof( fpIn ) ) + { + fread( buffer, 1, 1, fpIn ); + fprintf( fpOut, "0x%02X, ", buffer[0] ); + i++; + + if ( i > 8 ) + { + fprintf( fpOut, "\n" ); + i = 0; + } + } + + if ( i > 0 ) + { + fprintf( fpOut, "\n" ); + } + + fprintf( fpOut, "};" ); + fclose( fpOut ); fclose( fpIn ); + return 0; } diff --git a/src/utils/genhdr.c b/src/utils/genhdr.c index 19484c5..4e8cca9 100644 --- a/src/utils/genhdr.c +++ b/src/utils/genhdr.c @@ -12,115 +12,142 @@ /* Generated on Thu Feb 17 10:57:01 2011, * by pycrc v0.7.1, http://www.tty1.net/pycrc/ */ -uint32_t crc_reflect(uint32_t data, size_t data_len) +uint32_t crc_reflect( uint32_t data, size_t data_len ) { unsigned int i; uint32_t ret; ret = data & 0x01; - for (i = 1; i < data_len; i++) + + for ( i = 1; i < data_len; i++ ) { data >>= 1; - ret = (ret << 1) | (data & 0x01); + ret = ( ret << 1 ) | ( data & 0x01 ); } + return ret; } -uint32_t crc_update(uint32_t crc, const uint8_t *buf, uint32_t len) { +uint32_t crc_update( uint32_t crc, const uint8_t *buf, uint32_t len ) +{ unsigned int i; uint32_t bit; uint8_t c; - while (len--) { + while ( len-- ) + { c = *buf++; - for (i = 0x01; i & 0xff; i <<= 1) { + + for ( i = 0x01; i & 0xff; i <<= 1 ) + { bit = crc & 0x80000000; - if (c & i) { + + if ( c & i ) + { bit = bit ? 0 : 1; } + crc <<= 1; - if (bit) { + + if ( bit ) + { crc ^= 0x04c11db7; } } + crc &= 0xffffffff; } + return crc & 0xffffffff; } -int main(int argc, char **argv) { - FILE *f; - size_t flen; +int main( int argc, char **argv ) +{ + FILE *f; + size_t flen; - if(argc < 3) { - printf("Usage: genhdr \n" - " input file: file to be headered\n" - " signature : magic value at start of header (4-char string)\n" - " version : firmware version (decimal uint32)\n" - "Output is written in place.\n"); - return 1; - } - if((f=fopen(argv[1], "rb+"))==NULL) { - printf("Unable to open input file %s", argv[1]); - perror(""); - return 1; - } - fseek(f,0,SEEK_END); - flen=ftell(f); + if ( argc < 3 ) + { + printf( "Usage: genhdr \n" + " input file: file to be headered\n" + " signature : magic value at start of header (4-char string)\n" + " version : firmware version (decimal uint32)\n" + "Output is written in place.\n" ); + return 1; + } - if(flen+256 < flen) { - printf("File too large ;)\n"); - return 1; - } - char *remaining = NULL; - uint32_t version = (uint32_t)strtol(argv[3], &remaining, 0); - if(*remaining) { - printf("could not parse version number (remaining portion: %s)\n", remaining); - fclose(f); - return 1; - } + if ( ( f = fopen( argv[1], "rb+" ) ) == NULL ) + { + printf( "Unable to open input file %s", argv[1] ); + perror( "" ); + return 1; + } - if(strlen(argv[2]) > 4) { - printf("Magic string '%s' too long. Truncated to 4 characters.\n", argv[2]); - } - uint8_t *buf = malloc(flen+256); - if(!buf) { - perror("malloc"); - } - memset(buf, 0xff, 256); - fseek(f, 0, SEEK_SET); - fread(buf+256, 1, flen, f); + fseek( f, 0, SEEK_END ); + flen = ftell( f ); - uint32_t crcc = 0xffffffff, crc; - crcc = crc_update(crcc, buf+256, flen); - crcc = crc_reflect(crcc, 32); - crc = crcc ^ 0xffffffff; + if ( flen + 256 < flen ) + { + printf( "File too large ;)\n" ); + return 1; + } - memset(buf, 0, 4); - strncpy((char*)buf, argv[2], 4); + char *remaining = NULL; + uint32_t version = ( uint32_t )strtol( argv[3], &remaining, 0 ); - buf[4] = ll8(version); - buf[5] = lh8(version); - buf[6] = hl8(version); - buf[7] = hh8(version); + if ( *remaining ) + { + printf( "could not parse version number (remaining portion: %s)\n", remaining ); + fclose( f ); + return 1; + } - buf[8] = ll8(flen); - buf[9] = lh8(flen); - buf[10] = hl8(flen); - buf[11] = hh8(flen); + if ( strlen( argv[2] ) > 4 ) + { + printf( "Magic string '%s' too long. Truncated to 4 characters.\n", argv[2] ); + } - buf[12] = ll8(crc); - buf[13] = lh8(crc); - buf[14] = hl8(crc); - buf[15] = hh8(crc); + uint8_t *buf = malloc( flen + 256 ); - buf[16] = ll8(crcc); - buf[17] = lh8(crcc); - buf[18] = hl8(crcc); - buf[19] = hh8(crcc); + if ( !buf ) + { + perror( "malloc" ); + } - fseek(f, 0, SEEK_SET); - fwrite(buf, 1, 256+flen, f); - fclose(f); - return 0; + memset( buf, 0xff, 256 ); + fseek( f, 0, SEEK_SET ); + fread( buf + 256, 1, flen, f ); + + uint32_t crcc = 0xffffffff, crc; + crcc = crc_update( crcc, buf + 256, flen ); + crcc = crc_reflect( crcc, 32 ); + crc = crcc ^ 0xffffffff; + + memset( buf, 0, 4 ); + strncpy( ( char * )buf, argv[2], 4 ); + + buf[4] = ll8( version ); + buf[5] = lh8( version ); + buf[6] = hl8( version ); + buf[7] = hh8( version ); + + buf[8] = ll8( flen ); + buf[9] = lh8( flen ); + buf[10] = hl8( flen ); + buf[11] = hh8( flen ); + + buf[12] = ll8( crc ); + buf[13] = lh8( crc ); + buf[14] = hl8( crc ); + buf[15] = hh8( crc ); + + buf[16] = ll8( crcc ); + buf[17] = lh8( crcc ); + buf[18] = hl8( crcc ); + buf[19] = hh8( crcc ); + + fseek( f, 0, SEEK_SET ); + fwrite( buf, 1, 256 + flen, f ); + fclose( f ); + return 0; } diff --git a/src/utils/lpcchksum.c b/src/utils/lpcchksum.c index 7f9a63a..da1be93 100644 --- a/src/utils/lpcchksum.c +++ b/src/utils/lpcchksum.c @@ -7,61 +7,73 @@ #include -uint32_t getu32(uint8_t *buffer) { - return buffer[0]+(buffer[1]<<8)+(buffer[2]<<16)+(buffer[3]<<24); +uint32_t getu32( uint8_t *buffer ) +{ + return buffer[0] + ( buffer[1] << 8 ) + ( buffer[2] << 16 ) + ( buffer[3] << 24 ); } -void putu32(uint8_t *buffer, uint32_t data) { - buffer[0]=(uint8_t)(data&0xff); - buffer[1]=(uint8_t)((data>>8)&0xff); - buffer[2]=(uint8_t)((data>>16)&0xff); - buffer[3]=(uint8_t)((data>>24)&0xff); +void putu32( uint8_t *buffer, uint32_t data ) +{ + buffer[0] = ( uint8_t )( data & 0xff ); + buffer[1] = ( uint8_t )( ( data >> 8 ) & 0xff ); + buffer[2] = ( uint8_t )( ( data >> 16 ) & 0xff ); + buffer[3] = ( uint8_t )( ( data >> 24 ) & 0xff ); } -int main(int argc, char **argv) { - FILE *bin; - uint32_t data; - size_t len; - int count; - uint8_t *buffer; +int main( int argc, char **argv ) +{ + FILE *bin; + uint32_t data; + size_t len; + int count; + uint8_t *buffer; - if(argc<2) { - fprintf(stderr, "Usage: %s \nThe original file will be modified!\n", argv[0]); - return 1; - } + if ( argc < 2 ) + { + fprintf( stderr, "Usage: %s \nThe original file will be modified!\n", argv[0] ); + return 1; + } - if((bin=fopen(argv[1], "rb"))==NULL) { - perror("could not open input file"); - return 1; - } - - fseek(bin, 0, SEEK_END); - len=ftell(bin); - fseek(bin, 0, SEEK_SET); - if((buffer=malloc(len))==NULL) { - perror("could not reserve memory"); - fclose(bin); - return 1; - } - fread(buffer, len, 1, bin); - fclose(bin); + if ( ( bin = fopen( argv[1], "rb" ) ) == NULL ) + { + perror( "could not open input file" ); + return 1; + } - data=0; - for(count=0; count<7; count++) { - data+=getu32(buffer+4*count); - } - printf("data=%x chksum=%x\n", data, ~data+1); - putu32(buffer+28,~data+1); + fseek( bin, 0, SEEK_END ); + len = ftell( bin ); + fseek( bin, 0, SEEK_SET ); - if((bin=fopen(argv[1], "wb"))==NULL) { - perror("could not open output file"); - return 1; - } + if ( ( buffer = malloc( len ) ) == NULL ) + { + perror( "could not reserve memory" ); + fclose( bin ); + return 1; + } - fwrite(buffer, len, 1, bin); - fclose(bin); - printf("done\n"); - free(buffer); + fread( buffer, len, 1, bin ); + fclose( bin ); - return 0; + data = 0; + + for ( count = 0; count < 7; count++ ) + { + data += getu32( buffer + 4 * count ); + } + + printf( "data=%x chksum=%x\n", data, ~data + 1 ); + putu32( buffer + 28, ~data + 1 ); + + if ( ( bin = fopen( argv[1], "wb" ) ) == NULL ) + { + perror( "could not open output file" ); + return 1; + } + + fwrite( buffer, len, 1, bin ); + fclose( bin ); + printf( "done\n" ); + free( buffer ); + + return 0; } diff --git a/src/xmodem.c b/src/xmodem.c index c8f1547..6ac89b1 100644 --- a/src/xmodem.c +++ b/src/xmodem.c @@ -5,35 +5,46 @@ #include "ff.h" #include "xmodem.h" -void xmodem_rxfile(FIL* fil) { - uint8_t rxbuf[XMODEM_BLKSIZE], sum=0/*, sender_sum*/; -/* uint8_t blknum, blknum2;*/ - uint8_t count; - uint32_t totalbytes = 0; - uint32_t totalwritten = 0; - UINT written; - FRESULT res; - uart_flush(); - do { - delay_ms(3000); - uart_putc(ASC_NAK); - } while (uart_getc() != ASC_SOH); - do { - /*blknum=*/uart_getc(); - /*blknum2=*/uart_getc(); - for(count=0; count