mirror of
https://github.com/dborth/fceugx.git
synced 2024-10-31 22:45:05 +01:00
port to libfat / devkitpro r15
This commit is contained in:
parent
05448c1115
commit
6f1dea5b2d
@ -42,7 +42,7 @@ LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map -Wl,--cref
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -logc -lm -lz -lsdcard
|
||||
LIBS := -logc -lm -lz
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
|
177
Makefile.orig
177
Makefile.orig
@ -1,177 +0,0 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
# Generic makefile for Gamecube projects
|
||||
#
|
||||
# Tab stops set to 4
|
||||
# | | | |
|
||||
# 0 1 2 3
|
||||
#---------------------------------------------------------------------------------
|
||||
# Clear the implicit built in rules
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# INCLUDES is a list of directories containing extra header files
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := fceugc
|
||||
BUILD := build
|
||||
SOURCES := source source/boards source/mappers source/input \
|
||||
source/mbshare source/drivers/common \
|
||||
source/drivers/gamecube source/roms \
|
||||
source/iplfont source/sz
|
||||
INCLUDES := include source/sz source/linux
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
MACHDEP = -DGEKKO -mcpu=750 -meabi -mhard-float
|
||||
CFLAGS = -g -Os -Wall $(MACHDEP) $(INCLUDE) -DFCEU_VERSION_NUMERIC=9812 -DNGC=1 \
|
||||
-DZLIB -DBIG_ENDIAN -DHAVE_ASPRINTF=1 -DSTDC \
|
||||
-D_SZ_ONE_DIRECTORY=1 -D_LZMA_IN_CB=1 -D_LZMA_OUT_READ
|
||||
|
||||
LDFLAGS = $(MACHDEP) -mogc -Wl,-Map,$(notdir $@).map -Wl,--cref
|
||||
|
||||
PREFIX := powerpc-gekko-
|
||||
|
||||
export PATH:= $(DEVKITPPC)/bin:$(PATH)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with
|
||||
#---------------------------------------------------------------------------------
|
||||
#LIBS := -logc -lm -lz -lbba -lsdcard
|
||||
LIBS := -logc -lm -lz -logcsys -lsdcard
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir))
|
||||
|
||||
export CC := $(PREFIX)gcc
|
||||
export CXX := $(PREFIX)g++
|
||||
export AR := $(PREFIX)ar
|
||||
export OBJCOPY := $(PREFIX)objcopy
|
||||
#---------------------------------------------------------------------------------
|
||||
# automatically build a list of object files for our project
|
||||
#---------------------------------------------------------------------------------
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
export LD := $(CC)
|
||||
else
|
||||
export LD := $(CXX)
|
||||
endif
|
||||
|
||||
export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(sFILES:.s=.o) $(SFILES:.S=.o)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# build a list of include paths
|
||||
#---------------------------------------------------------------------------------
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# build a list of library paths
|
||||
#---------------------------------------------------------------------------------
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
.PHONY: $(BUILD) clean
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) *.elf
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
run:
|
||||
psoload $(TARGET).dol
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
reload:
|
||||
psoload -r $(TARGET).dol
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(OUTPUT).dol: $(OUTPUT).elf
|
||||
@echo output ... $(notdir $@)
|
||||
@$(OBJCOPY) -O binary $< $@
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(OUTPUT).elf: $(OFILES)
|
||||
@echo linking ... $(notdir $@)
|
||||
@$(LD) $^ $(LDFLAGS) $(LIBPATHS) $(LIBS) -o $@
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# Compile Targets for C/C++
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o : %.cpp
|
||||
@echo $(notdir $<)
|
||||
@$(CXX) -MMD $(CFLAGS) -o $@ -c $<
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o : %.c
|
||||
@echo $(notdir $<)
|
||||
@$(CC) -MMD $(CFLAGS) -o $@ -c $<
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o : %.S
|
||||
@echo $(notdir $<)
|
||||
@$(CC) -MMD $(CFLAGS) -D_LANGUAGE_ASSEMBLY -c $< -o $@
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o : %.s
|
||||
@echo $(notdir $<)
|
||||
@$(CC) -MMD $(CFLAGS) -D_LANGUAGE_ASSEMBLY -c $< -o $@
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# canned command sequence for binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
define bin2o
|
||||
cp $(<) $(*).tmp
|
||||
$(OBJCOPY) -I binary -O elf32-powerpc -B powerpc \
|
||||
--rename-section .data=.rodata,readonly,data,contents,alloc \
|
||||
--redefine-sym _binary_$*_tmp_start=$*\
|
||||
--redefine-sym _binary_$*_tmp_end=$*_end\
|
||||
--redefine-sym _binary_$*_tmp_size=$*_size\
|
||||
$(*).tmp $(@)
|
||||
echo "extern const u8" $(*)"[];" > $(*).h
|
||||
echo "extern const u32" $(*)_size[]";" >> $(*).h
|
||||
rm $(*).tmp
|
||||
endef
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
@ -1,4 +0,0 @@
|
||||
cp Makefile.orig Makefile
|
||||
make
|
||||
rm Makefile
|
||||
rm -d build/*.*
|
13
Makefile.wii
13
Makefile.wii
@ -21,9 +21,9 @@ BUILD := build
|
||||
SOURCES := source source/boards source/mappers source/input \
|
||||
source/mbshare source/drivers/common \
|
||||
source/drivers/gamecube source/roms \
|
||||
source/iplfont source/sz source/drivers/gamecube/wiisd
|
||||
source/iplfont source/sz
|
||||
DATA := data
|
||||
INCLUDES := source source/sz source/drivers/gamecube/wiisd
|
||||
INCLUDES := source source/sz
|
||||
# Specify language in all capitals
|
||||
# Supported languages: ENGLISH DUTCH
|
||||
LANG := ENGLISH
|
||||
@ -44,7 +44,7 @@ LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map -Wl,--cref
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -logc -lm -lz -lsdcard
|
||||
LIBS := -ldb -lfat -logc -lm -lz
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
@ -156,15 +156,12 @@ tags:
|
||||
mbshare/*.c mbshare/*.h \
|
||||
drivers/common/*.c drivers/common/*.h \
|
||||
drivers/gamecube/*.c drivers/gamecube/*.h \
|
||||
drivers/gamecube/wiisd/*.h drivers/gamecube/wiisd/*.c \
|
||||
drivers/gamecube/intl/english.h \
|
||||
iplfont/*.c iplfont/*.h \
|
||||
sz/*.c sz/*.h \
|
||||
/opt/devkitpro/libogc/include/*.h \
|
||||
/opt/devkitpro/libogc/include/mad/*.h \
|
||||
/opt/devkitpro/libogc/include/ogc/*.h \
|
||||
/opt/devkitpro/libogc/include/modplay/*.h \
|
||||
/opt/devkitpro/libogc/include/sdcard/*.h \
|
||||
/opt/devkitpro/libjpeg/include/jpeg/*.h \
|
||||
/opt/devkitpro/libfreetype/include/*.h \
|
||||
/opt/devkitpro/libfreetype/include/freetype/*.h )
|
||||
/opt/devkitpro/libogc/include/sdcard/*.h )
|
||||
|
||||
|
@ -1,166 +0,0 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
# Clear the implicit built in rules
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(DEVKITPPC)),)
|
||||
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
|
||||
endif
|
||||
|
||||
include $(DEVKITPPC)/wii_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# INCLUDES is a list of directories containing extra header files
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := fceu_wii_pal60
|
||||
BUILD := build
|
||||
#SOURCES := source source/sz source/boards source/linux source/linux/bits source/linux/gnu source/palettes source/fir source/input source/rom source/mappers source/mbshare source/drivers source/drivers/common source/drivers/gamecube source/iplfont
|
||||
SOURCES := source source/boards source/mappers source/input \
|
||||
source/mbshare source/drivers/common \
|
||||
source/drivers/gamecube source/roms \
|
||||
source/iplfont source/sz source/drivers/gamecube/wiisd
|
||||
DATA := data
|
||||
INCLUDES := source/sz source/drivers/gamecube/wiisd
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
#CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE) -DFCEU_VERSION_NUMERIC=9812 -DNGC=1 -DZLIB -DBIG_ENDIAN -DHAVE_ASPRINTF=1 -DSTDC -D_SZ_ONE_DIRECTORY=1 -D_LZMA_IN_CB=1 -D_LZMA_OUT_READ
|
||||
CFLAGS = -g -Os -Wall $(MACHDEP) $(INCLUDE) -DFCEU_VERSION_NUMERIC=9812 -DNGC=1 \
|
||||
-DZLIB -DBIG_ENDIAN -DHAVE_ASPRINTF=1 -DSTDC \
|
||||
-D_SZ_ONE_DIRECTORY=1 -D_LZMA_IN_CB=1 -D_LZMA_OUT_READ -DFORCE_EURGB60
|
||||
CXXFLAGS = $(CFLAGS)
|
||||
|
||||
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map -Wl,--cref
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -logc -lm -lz -lsdcard
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# automatically build a list of object files for our project
|
||||
#---------------------------------------------------------------------------------
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
export LD := $(CC)
|
||||
else
|
||||
export LD := $(CXX)
|
||||
endif
|
||||
|
||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
|
||||
$(sFILES:.s=.o) $(SFILES:.S=.o)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# build a list of include paths
|
||||
#---------------------------------------------------------------------------------
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD) \
|
||||
-I$(LIBOGC_INC)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# build a list of library paths
|
||||
#---------------------------------------------------------------------------------
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
|
||||
-L$(LIBOGC_LIB)
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
.PHONY: $(BUILD) clean
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol source/tags
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
run:
|
||||
psoload $(TARGET).dol
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
reload:
|
||||
psoload -r $(TARGET).dol
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(OUTPUT).dol: $(OUTPUT).elf
|
||||
$(OUTPUT).elf: $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# This rule links in binary data with the .jpg extension
|
||||
#---------------------------------------------------------------------------------
|
||||
%.jpg.o : %.jpg
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
$(bin2o)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
tags:
|
||||
@( cd source; ctags *.c *.h \
|
||||
boards/*.c boards/*.h \
|
||||
mappers/*.c mappers/*.h \
|
||||
input/*.c input/*.h \
|
||||
mbshare/*.c mbshare/*.h \
|
||||
drivers/common/*.c drivers/common/*.h \
|
||||
drivers/gamecube/*.c drivers/gamecube/*.h \
|
||||
drivers/gamecube/wiisd/*.h drivers/gamecube/wiisd/*.c \
|
||||
iplfont/*.c iplfont/*.h \
|
||||
sz/*.c sz/*.h \
|
||||
/opt/devkitpro/libogc/include/*.h \
|
||||
/opt/devkitpro/libogc/include/mad/*.h \
|
||||
/opt/devkitpro/libogc/include/ogc/*.h \
|
||||
/opt/devkitpro/libogc/include/modplay/*.h \
|
||||
/opt/devkitpro/libogc/include/sdcard/*.h \
|
||||
/opt/devkitpro/libjpeg/include/jpeg/*.h \
|
||||
/opt/devkitpro/libfreetype/include/*.h \
|
||||
/opt/devkitpro/libfreetype/include/freetype/*.h )
|
||||
|
@ -10,19 +10,21 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sdcard.h>
|
||||
#include <gctypes.h>
|
||||
|
||||
#include <sys/dir.h>
|
||||
#include "sz.h"
|
||||
#include "gcdvd.h"
|
||||
|
||||
#ifdef HW_RVL
|
||||
#include "wiisd/vfat.h"
|
||||
FILE *filehandle = NULL;
|
||||
|
||||
/*Front SCARD*/
|
||||
VFATFS vfs;
|
||||
FSDIRENTRY vfsfile;
|
||||
#endif
|
||||
#define MAXFILES 1000
|
||||
// From libfat MAX_FILENAME_LENGTH
|
||||
#define MAX_PATH_LEN 768
|
||||
typedef struct {
|
||||
char filename[MAX_PATH_LEN+1];
|
||||
u64 offset;
|
||||
unsigned int length;
|
||||
char flags;
|
||||
}FILEENTRIES;
|
||||
|
||||
/*** Simplified Directory Entry Record
|
||||
I only care about a couple of values ***/
|
||||
@ -62,9 +64,9 @@ extern bool isWii;
|
||||
extern int WiiSD_Available;
|
||||
u8 UseSDCARD = 0;
|
||||
u8 UseWiiSDCARD = 0;
|
||||
sd_file * filehandle = NULL;
|
||||
char rootSDdir[SDCARD_MAX_PATH_LEN];
|
||||
char rootWiiSDdir[SDCARD_MAX_PATH_LEN];
|
||||
|
||||
char rootSDdir[MAX_PATH_LEN];
|
||||
char rootWiiSDdir[MAX_PATH_LEN];
|
||||
int haveSDdir = 0;
|
||||
int haveWiiSDdir = 0;
|
||||
int sdslot = 0;
|
||||
@ -75,10 +77,7 @@ int sdslot = 0;
|
||||
* These are here simply because the same functions in libogc are not
|
||||
* exposed to the user
|
||||
****************************************************************************/
|
||||
|
||||
void dvd_inquiry()
|
||||
{
|
||||
|
||||
void dvd_inquiry() {
|
||||
dvd[0] = 0x2e;
|
||||
dvd[1] = 0;
|
||||
dvd[2] = 0x12000000;
|
||||
@ -90,10 +89,18 @@ void dvd_inquiry()
|
||||
|
||||
while( dvd[7] & 1 );
|
||||
DCFlushRange((void *)0x80000000, 32);
|
||||
|
||||
/*** Get Drive Type ***/
|
||||
unsigned char *inquiry=(unsigned char *)0x80000004;
|
||||
int driveid = (int)inquiry[2];
|
||||
|
||||
/*** Make sure it's one I now about ***/
|
||||
if ( ( driveid != 4 ) && ( driveid != 6 ) && ( driveid != 8 ) ) {
|
||||
isWii = true; // Wii in GC mode
|
||||
}
|
||||
}
|
||||
|
||||
void dvd_unlock()
|
||||
{
|
||||
void dvd_unlock() {
|
||||
dvd[0] |= 0x00000014;
|
||||
dvd[1] = 0x00000000;
|
||||
dvd[2] = 0xFF014D41;
|
||||
@ -304,7 +311,7 @@ int IsPVD() {
|
||||
****************************************************************************/
|
||||
static int diroffset = 0;
|
||||
int getfiles( int filecount ) {
|
||||
char fname[MAXJOLIET+1];
|
||||
char fname[MAX_PATH_LEN+1];
|
||||
char *ptr;
|
||||
char *filename;
|
||||
char *filenamelength;
|
||||
@ -340,7 +347,7 @@ int getfiles( int filecount ) {
|
||||
|
||||
fname[j] = 0;
|
||||
|
||||
if ( strlen(fname) >= MAXJOLIET ) fname[MAXJOLIET] = 0;
|
||||
if ( strlen(fname) >= MAX_PATH_LEN ) fname[MAX_PATH_LEN] = 0;
|
||||
if ( strlen(fname) == 0 ) fname[0] = filename[0];
|
||||
}
|
||||
|
||||
@ -380,6 +387,7 @@ int getfiles( int filecount ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __gamecube__
|
||||
/****************************************************************************
|
||||
* ParseDirectory
|
||||
*
|
||||
@ -416,6 +424,7 @@ int parsedir() {
|
||||
}
|
||||
return filecount;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************************
|
||||
* Update SDCARD curent directory name
|
||||
@ -433,10 +442,10 @@ int updateSDdirname() {
|
||||
if (strcmp(filelist[selection].filename,"..") == 0) {
|
||||
/* determine last subdirectory namelength */
|
||||
sprintf(temp,"%s",rootSDdir);
|
||||
test = strtok(temp,"\\");
|
||||
test = strtok(temp,"/");
|
||||
while (test != NULL) {
|
||||
size = strlen(test);
|
||||
test = strtok(NULL,"\\");
|
||||
test = strtok(NULL,"/");
|
||||
}
|
||||
|
||||
/* remove last subdirectory name */
|
||||
@ -445,17 +454,17 @@ int updateSDdirname() {
|
||||
|
||||
/* handles root name */
|
||||
//sprintf(tmpCompare, "dev%d:",ChosenSlot);
|
||||
if (strcmp(rootSDdir, sdslot ? "dev1:":"dev0:") == 0)
|
||||
sprintf(rootSDdir,"dev%d:\\%s\\..", sdslot, FCEUDIR);
|
||||
if (strcmp(rootSDdir, "/") == 0)
|
||||
sprintf(rootSDdir,"fat:/");
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
/* test new directory namelength */
|
||||
if ((strlen(rootSDdir)+1+strlen(filelist[selection].filename)) < SDCARD_MAX_PATH_LEN) {
|
||||
if ((strlen(rootSDdir)+1+strlen(filelist[selection].filename)) < MAX_PATH_LEN) {
|
||||
/* handles root name */
|
||||
sprintf(temp, "dev%d:\\%s\\..", sdslot, FCEUDIR);
|
||||
sprintf(temp, "/%s/..", FCEUDIR);
|
||||
if (strcmp(rootSDdir, temp) == 0)
|
||||
sprintf(rootSDdir,"dev%d:",sdslot);
|
||||
sprintf(rootSDdir,"fat:/");
|
||||
|
||||
/* update current directory name */
|
||||
sprintf(rootSDdir, "%s\\%s",rootSDdir, filelist[selection].filename);
|
||||
@ -467,122 +476,50 @@ int updateSDdirname() {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HW_RVL
|
||||
/***************************************************************************
|
||||
* * Update WiiSDCARD curent directory name
|
||||
* ***************************************************************************/
|
||||
int updateWiiSDdirname() {
|
||||
int size=0;
|
||||
char *test;
|
||||
char temp[1024];
|
||||
|
||||
/* current directory doesn't change */
|
||||
if (strcmp(filelist[selection].filename,".") == 0)
|
||||
return 0;
|
||||
|
||||
/* go up to parent directory */
|
||||
else if (strcmp(filelist[selection].filename,"..") == 0) {
|
||||
/* determine last subdirectory namelength */
|
||||
sprintf(temp,"%s",rootWiiSDdir);
|
||||
test = strtok(temp,"/");
|
||||
while (test != NULL) {
|
||||
size = strlen(test);
|
||||
test = strtok(NULL,"/");
|
||||
}
|
||||
|
||||
/* remove last subdirectory name */
|
||||
size = strlen(rootWiiSDdir) - size - 1;
|
||||
rootWiiSDdir[size] = 0;
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
/* test new directory namelength */
|
||||
if ((strlen(rootWiiSDdir)+1+strlen(filelist[selection].filename)) < SDCARD_MAX_PATH_LEN) {
|
||||
/* update current directory name */
|
||||
sprintf(rootWiiSDdir, "%s/%s",rootWiiSDdir, filelist[selection].filename);
|
||||
return 1;
|
||||
} else {
|
||||
WaitPrompt ((char*)"Dirname is too long !");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************************
|
||||
* Browse SDCARD subdirectories
|
||||
***************************************************************************/
|
||||
int parseSDdirectory() {
|
||||
int entries = 0;
|
||||
int nbfiles = 0;
|
||||
int numstored = 0;
|
||||
DIR *sddir = NULL;
|
||||
DIR_ITER *sddir = NULL;
|
||||
char msg[128];
|
||||
char filename[MAX_PATH_LEN];
|
||||
struct stat filestat;
|
||||
|
||||
/* initialize selection */
|
||||
selection = offset = 0;
|
||||
|
||||
/* Get a list of files from the actual root directory */
|
||||
entries = SDCARD_ReadDir (rootSDdir, &sddir);
|
||||
//entries = SDCARD_ReadDir (sdcardpath, &sddir);
|
||||
// If rootSDdir doesn't exist, default to the root dir
|
||||
sddir = diropen(rootSDdir);
|
||||
if (sddir == NULL) {
|
||||
strcpy(rootSDdir, "fat:/");
|
||||
sddir = diropen(rootSDdir);
|
||||
WaitPrompt(msg);
|
||||
if (sddir == NULL) {
|
||||
sprintf(msg, "Error opening %s", rootSDdir);
|
||||
WaitPrompt(msg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (entries <= 0) entries = 0;
|
||||
if (entries>MAXFILES) entries = MAXFILES;
|
||||
|
||||
while (entries)
|
||||
{
|
||||
if (strcmp((const char*)sddir[nbfiles].fname, ".") != 0) { // Skip "." directory
|
||||
memset (&filelist[numstored], 0, sizeof (FILEENTRIES));
|
||||
strncpy(filelist[numstored].filename,(const char*)sddir[nbfiles].fname,MAXJOLIET);
|
||||
filelist[numstored].filename[MAXJOLIET-1] = 0;
|
||||
filelist[numstored].length = sddir[nbfiles].fsize;
|
||||
filelist[numstored].flags = (char)(sddir[nbfiles].fattr & SDCARD_ATTR_DIR);
|
||||
while (dirnext(sddir, filename, &filestat) == 0) {
|
||||
if ((strcmp(filename, ".") != 0) && (numstored < MAXFILES)) {
|
||||
memset(&filelist[numstored], 0, sizeof (FILEENTRIES));
|
||||
strncpy(filelist[numstored].filename, filename, MAX_PATH_LEN);
|
||||
filelist[numstored].length = filestat.st_size;
|
||||
filelist[numstored].flags = (filestat.st_mode & S_IFDIR) ? 1 : 0;
|
||||
sprintf(msg, "Found #%d: %s", numstored, filename);
|
||||
ShowAction(msg);
|
||||
numstored++;
|
||||
}
|
||||
nbfiles++;
|
||||
entries--;
|
||||
}
|
||||
|
||||
free(sddir);
|
||||
|
||||
return nbfiles;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Browse WiiSD subdirectories
|
||||
***************************************************************************/
|
||||
#ifdef HW_RVL
|
||||
int parseWiiSDdirectory() {
|
||||
int entries = 0;
|
||||
int nbfiles = 0;
|
||||
int numstored = 0;
|
||||
char msg[1024];
|
||||
|
||||
/* initialize selection */
|
||||
selection = offset = 0;
|
||||
|
||||
/* Get a list of files from the actual root directory */
|
||||
FSDIRENTRY vfsdir;
|
||||
int result = VFAT_opendir(0, &vfsdir, rootWiiSDdir);
|
||||
if(result != FS_SUCCESS) {
|
||||
sprintf(msg, "Opendir(%s) failed with %d.", rootWiiSDdir, result);
|
||||
WaitPrompt(msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (VFAT_readdir(&vfsdir) == FS_SUCCESS) {
|
||||
memset (&filelist[numstored], 0, sizeof (FILEENTRIES));
|
||||
strncpy(filelist[numstored].filename,(char *)(vfsdir.longname), MAX_LONG_NAME);
|
||||
filelist[numstored].filename[MAX_LONG_NAME-1] = 0;
|
||||
filelist[numstored].length = vfsdir.fsize;
|
||||
filelist[numstored].flags = (char)(vfsdir.dirent.attribute & ATTR_DIRECTORY);
|
||||
numstored++;
|
||||
nbfiles++;
|
||||
}
|
||||
VFAT_closedir(&vfsdir);
|
||||
|
||||
dirclose(sddir);
|
||||
sprintf(msg, "Found %d items.", numstored);
|
||||
WaitPrompt(msg);
|
||||
_break();
|
||||
return numstored;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* ShowFiles
|
||||
@ -635,7 +572,6 @@ extern u8 PADCAL;
|
||||
|
||||
void FileSelector() {
|
||||
short p;
|
||||
short q = 0;
|
||||
signed char a;
|
||||
int haverom = 0;
|
||||
int redraw = 1;
|
||||
@ -687,6 +623,7 @@ void FileSelector() {
|
||||
}
|
||||
|
||||
if ( p & PAD_BUTTON_A ) {
|
||||
_break();
|
||||
if ( filelist[selection].flags ) { /*** This is directory ***/
|
||||
if (UseSDCARD) {
|
||||
//if ( filelist[selection].filename[0] == 0x2e) {
|
||||
@ -699,33 +636,19 @@ void FileSelector() {
|
||||
haverom = 1; // quit SD menu
|
||||
haveSDdir = 0; // reset everything at next access
|
||||
}
|
||||
}
|
||||
else if (status == -1) {
|
||||
} else if (status == -1) {
|
||||
haverom = 1; // quit SD menu
|
||||
haveSDdir = 0; // reset everything at next access
|
||||
}
|
||||
#ifdef HW_RVL
|
||||
} else if (UseWiiSDCARD) {
|
||||
/* update current directory and set new entry list if directory has changed */
|
||||
int status = updateWiiSDdirname();
|
||||
if (status == 1) {
|
||||
maxfiles = parseWiiSDdirectory();
|
||||
if (!maxfiles) {
|
||||
WaitPrompt ((char*)"Error reading directory !");
|
||||
haverom = 1; // quit SD menu
|
||||
haveWiiSDdir = 0; // reset everything at next access
|
||||
}
|
||||
} else if (status == -1) {
|
||||
haverom = 1; // quit SD menu
|
||||
haveWiiSDdir = 0; // reset everything at next access
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
#ifdef __gamecube__
|
||||
} else { // DVD
|
||||
rootdir = filelist[selection].offset;
|
||||
rootdirlength = filelist[selection].length;
|
||||
offset = selection = 0;
|
||||
maxfiles = parsedir();
|
||||
#endif
|
||||
}
|
||||
#ifdef __gamecube__
|
||||
} else if (selection == 0 && inSz == true) {
|
||||
rootdir = filelist[1].offset;
|
||||
rootdirlength = filelist[1].length;
|
||||
@ -735,7 +658,7 @@ void FileSelector() {
|
||||
SzClose();
|
||||
} else if (inSz == false && SzDvdIsArchive(filelist[selection].offset) == SZ_OK) {
|
||||
// parse the 7zip file
|
||||
WaitPrompt("Found 7z");
|
||||
ShowAction("Found 7z");
|
||||
SzParse();
|
||||
if(SzRes == SZ_OK) {
|
||||
inSz = true;
|
||||
@ -755,6 +678,7 @@ void FileSelector() {
|
||||
offset = selection = 0;
|
||||
maxfiles = parsedir();
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
rootdir = filelist[selection].offset;
|
||||
rootdirlength = filelist[selection].length;
|
||||
@ -775,49 +699,39 @@ int LoadDVDFile( unsigned char *buffer ) {
|
||||
int blocks;
|
||||
int i;
|
||||
u64 discoffset;
|
||||
|
||||
#ifdef HW_RVL
|
||||
if(UseWiiSDCARD) {
|
||||
ShowAction((char*)"Loading ... Wait");
|
||||
char filename[1024];
|
||||
sprintf(filename, "%s/%s", rootWiiSDdir, filelist[selection].filename);
|
||||
|
||||
int res = VFAT_fopen(0, &vfsfile, filename, FS_READ);
|
||||
if (res != FS_SUCCESS) {
|
||||
char msg[1024];
|
||||
sprintf(msg, "Open %s failed, error %d", filename, res);
|
||||
WaitPrompt(msg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
char fname[MAX_PATH_LEN];
|
||||
|
||||
/*** SDCard Addition ***/
|
||||
if (UseSDCARD) GetSDInfo();
|
||||
if (rootdirlength == 0) return 0;
|
||||
|
||||
/* Check filename length */
|
||||
if ((strlen(rootSDdir)+1+strlen(filelist[selection].filename)) < MAX_PATH_LEN)
|
||||
sprintf(fname, "%s/%s",rootSDdir,filelist[selection].filename);
|
||||
else {
|
||||
WaitPrompt ("Maximum Filename Length reached !");
|
||||
haveSDdir = 0; // reset everything before next access
|
||||
}
|
||||
|
||||
filehandle = fopen(fname, "rb");
|
||||
if (filehandle == NULL) {
|
||||
WaitPrompt ("Unable to open file!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*** How many 2k blocks to read ***/
|
||||
blocks = rootdirlength / 2048;
|
||||
offset = 0;
|
||||
discoffset = rootdir;
|
||||
|
||||
ShowAction("Loading ... Wait");
|
||||
if (UseSDCARD) SDCARD_ReadFile (filehandle, &readbuffer, 2048);
|
||||
#ifdef HW_RVL
|
||||
else if (UseWiiSDCARD) VFAT_fread(&vfsfile, &readbuffer, 2048);
|
||||
#endif
|
||||
if (UseSDCARD) fread(&readbuffer, 2048, 1, filehandle);
|
||||
else dvd_read(&readbuffer, 2048, discoffset);
|
||||
|
||||
if ( isZipFile() == false ) {
|
||||
if (UseSDCARD) SDCARD_SeekFile (filehandle, 0, SDCARD_SEEK_SET);
|
||||
#ifdef HW_RVL
|
||||
else if (UseWiiSDCARD) VFAT_fseek(&vfsfile, 0, SEEK_SET);
|
||||
#endif
|
||||
if (isZipFile() == false) {
|
||||
if (UseSDCARD) fseek(filehandle, 0, SEEK_SET);
|
||||
for ( i = 0; i < blocks; i++ ) {
|
||||
if (UseSDCARD) SDCARD_ReadFile (filehandle, &readbuffer, 2048);
|
||||
#ifdef HW_RVL
|
||||
else if (UseWiiSDCARD) VFAT_fread(&vfsfile, &readbuffer, 2048);
|
||||
#endif
|
||||
if (UseSDCARD) fread(&readbuffer, 2048, 1, filehandle);
|
||||
else dvd_read(&readbuffer, 2048, discoffset);
|
||||
memcpy(&buffer[offset], &readbuffer, 2048);
|
||||
offset += 2048;
|
||||
@ -827,24 +741,19 @@ int LoadDVDFile( unsigned char *buffer ) {
|
||||
/*** And final cleanup ***/
|
||||
if( rootdirlength % 2048 ) {
|
||||
i = rootdirlength % 2048;
|
||||
if (UseSDCARD) SDCARD_ReadFile (filehandle, &readbuffer, i);
|
||||
#ifdef HW_RVL
|
||||
else if (UseWiiSDCARD) VFAT_fread(&vfsfile, &readbuffer, i);
|
||||
#endif
|
||||
if (UseSDCARD) fread(&readbuffer, i, 1, filehandle);
|
||||
else dvd_read(&readbuffer, 2048, discoffset);
|
||||
memcpy(&buffer[offset], &readbuffer, i);
|
||||
}
|
||||
} else {
|
||||
return unzipDVDFile( buffer, (u32)discoffset, rootdirlength);
|
||||
}
|
||||
if (UseSDCARD) SDCARD_CloseFile (filehandle);
|
||||
#ifdef HW_RVL
|
||||
else if (UseWiiSDCARD) VFAT_fclose(&vfsfile);
|
||||
#endif
|
||||
if (UseSDCARD) fclose(filehandle);
|
||||
|
||||
return rootdirlength;
|
||||
}
|
||||
|
||||
#ifdef __gamecube__
|
||||
/****************************************************************************
|
||||
* OpenDVD
|
||||
*
|
||||
@ -852,18 +761,18 @@ int LoadDVDFile( unsigned char *buffer ) {
|
||||
* For Viper/Qoob users, sector 0 is read, and if it contains all nulls
|
||||
* an ISO disc is assumed.
|
||||
****************************************************************************/
|
||||
static int havedir = 0;
|
||||
static int haveDVDdir = 0;
|
||||
int OpenDVD() {
|
||||
haveSDdir = 0;
|
||||
|
||||
havedir = offset = selection = 0;
|
||||
haveDVDdir = offset = selection = 0;
|
||||
|
||||
// Mount the DVD if necessary
|
||||
if (!IsPVD()) {
|
||||
ShowAction("Mounting DVD");
|
||||
DVD_Mount();
|
||||
ShowAction("Done Mounting");
|
||||
havedir = 0;
|
||||
haveDVDdir = 0;
|
||||
if (!IsPVD()) {
|
||||
WaitPrompt("No vallid ISO9660 DVD");
|
||||
return 0; // No correct ISO9660 DVD
|
||||
@ -871,14 +780,14 @@ int OpenDVD() {
|
||||
}
|
||||
|
||||
/*** At this point I should have an unlocked DVD ... so let's do the ISO ***/
|
||||
if ( havedir != 1 ) {
|
||||
if ( haveDVDdir != 1 ) {
|
||||
if ( IsPVD() ) {
|
||||
/*** Have a valid PVD, so start reading directory entries ***/
|
||||
maxfiles = parsedir();
|
||||
if ( maxfiles ) {
|
||||
offset = selection = 0;
|
||||
FileSelector();
|
||||
havedir = 1;
|
||||
haveDVDdir = 1;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
@ -888,85 +797,29 @@ int OpenDVD() {
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef HW_RVL
|
||||
int OpenWiiSD () {
|
||||
UseWiiSDCARD = 1;
|
||||
UseSDCARD = 0;
|
||||
haveSDdir = 0;
|
||||
char msg[128];
|
||||
|
||||
/*if (WiiSD_Available == 0) {
|
||||
sprintf(msg, "Insert SD card: %d\n", WiiSD_Available);
|
||||
WaitPrompt(msg);
|
||||
//return 0;
|
||||
}*/
|
||||
|
||||
memset(&vfs, 0, sizeof(VFATFS));
|
||||
if (haveWiiSDdir == 0) {
|
||||
/* don't mess with DVD entries */
|
||||
havedir = 0;
|
||||
|
||||
/* Mount WiiSD with VFAT */
|
||||
VFAT_unmount(0, &vfs);
|
||||
int res = VFAT_mount(FS_SLOTA, &vfs);
|
||||
if (res != FS_TYPE_FAT16) {
|
||||
sprintf(msg, "Error mounting WiiSD: %d", res);
|
||||
WaitPrompt(msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Reset SDCARD root directory */
|
||||
sprintf(rootWiiSDdir,"/%s/%s", FCEUDIR, ROMSDIR);
|
||||
|
||||
/* Parse initial root directory and get entries list */
|
||||
ShowAction((char *)"Reading Directory ...");
|
||||
if ((maxfiles = parseWiiSDdirectory ())) {
|
||||
sprintf (msg, "Found %d entries", maxfiles);
|
||||
ShowAction(msg);
|
||||
/* Select an entry */
|
||||
FileSelector ();
|
||||
|
||||
/* memorize last entries list, actual root directory and selection for next access */
|
||||
/* TODO: Bugged, do not activate cached dir listing
|
||||
haveWiiSDdir = 1;*/
|
||||
} else {
|
||||
/* no entries found */
|
||||
sprintf (msg, "Error reading %s", rootWiiSDdir);
|
||||
WaitPrompt (msg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Retrieve previous entries list and made a new selection */
|
||||
else FileSelector ();
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int OpenSD () {
|
||||
int OpenSD() {
|
||||
UseSDCARD = 1;
|
||||
UseWiiSDCARD = 0;
|
||||
haveWiiSDdir = 0;
|
||||
char msg[128];
|
||||
|
||||
if (ChosenSlot != sdslot) haveSDdir = 0;
|
||||
|
||||
if (haveSDdir == 0) {
|
||||
#ifdef __gamecube__
|
||||
/* don't mess with DVD entries */
|
||||
havedir = 0;
|
||||
haveDVDdir = 0;
|
||||
#endif
|
||||
|
||||
/* Reset SDCARD root directory */
|
||||
sprintf(rootSDdir,"dev%d:\\%s\\%s", ChosenSlot, FCEUDIR, ROMSDIR);
|
||||
sdslot = ChosenSlot;
|
||||
|
||||
sprintf(rootSDdir,"/%s/%s", FCEUDIR, ROMSDIR);
|
||||
/* Parse initial root directory and get entries list */
|
||||
ShowAction("Reading Directory ...");
|
||||
if ((maxfiles = parseSDdirectory ())) {
|
||||
//_break();
|
||||
maxfiles = parseSDdirectory();
|
||||
if (maxfiles) {
|
||||
sprintf (msg, "Found %d entries", maxfiles);
|
||||
ShowAction(msg);
|
||||
WaitPrompt(msg);
|
||||
/* Select an entry */
|
||||
FileSelector ();
|
||||
FileSelector();
|
||||
|
||||
/* memorize last entries list, actual root directory and selection for next access */
|
||||
haveSDdir = 1;
|
||||
@ -978,7 +831,7 @@ int OpenSD () {
|
||||
}
|
||||
}
|
||||
/* Retrieve previous entries list and made a new selection */
|
||||
else FileSelector ();
|
||||
else FileSelector();
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -987,24 +840,17 @@ int OpenSD () {
|
||||
* SDCard Get Info
|
||||
****************************************************************************/
|
||||
void GetSDInfo () {
|
||||
char fname[SDCARD_MAX_PATH_LEN];
|
||||
char fname[MAX_PATH_LEN];
|
||||
struct stat fstat;
|
||||
DIR_ITER *dir;
|
||||
|
||||
rootdirlength = 0;
|
||||
|
||||
/* Check filename length */
|
||||
if ((strlen(rootSDdir)+1+strlen(filelist[selection].filename)) < SDCARD_MAX_PATH_LEN)
|
||||
sprintf(fname, "%s\\%s",rootSDdir,filelist[selection].filename);
|
||||
|
||||
else
|
||||
{
|
||||
WaitPrompt ("Maximum Filename Length reached !");
|
||||
haveSDdir = 0; // reset everything before next access
|
||||
dir = diropen(rootSDdir);
|
||||
if (dir != NULL) {
|
||||
while(dirnext(dir, fname, &fstat) == 0) {
|
||||
if (strcmp(fname, filelist[selection].filename) == 0)
|
||||
rootdirlength = fstat.st_size;
|
||||
}
|
||||
dirclose(dir);
|
||||
}
|
||||
|
||||
filehandle = SDCARD_OpenFile (fname, "rb");
|
||||
if (filehandle == NULL)
|
||||
{
|
||||
WaitPrompt ("Unable to open file!");
|
||||
return;
|
||||
}
|
||||
rootdirlength = SDCARD_GetFileSize (filehandle);
|
||||
}
|
||||
|
@ -1,14 +0,0 @@
|
||||
#include <sdcard.h>
|
||||
|
||||
#define MAXJOLIET 256
|
||||
#define MAXFILES 1000
|
||||
|
||||
typedef struct {
|
||||
char filename[MAXJOLIET+1];
|
||||
char sdcardpath[SDCARD_MAX_PATH_LEN];
|
||||
u64 offset;
|
||||
unsigned int length;
|
||||
char flags;
|
||||
}FILEENTRIES;
|
||||
|
||||
extern FILEENTRIES filelist[MAXFILES];
|
@ -34,51 +34,43 @@ struct pcpal {
|
||||
unsigned int gcpalette[256]; /*** Much simpler GC palette ***/
|
||||
unsigned short rgb565[256]; /*** Texture map palette ***/
|
||||
static unsigned char gp_fifo[DEFAULT_FIFO_SIZE] __attribute__((__aligned__(32)));
|
||||
static unsigned char texturemem[ TEX_WIDTH * TEX_HEIGHT * 2 ] __attribute__((__aligned__(32)));
|
||||
static unsigned char texturemem[TEX_WIDTH * TEX_HEIGHT * 2] __attribute__((__aligned__(32)));
|
||||
GXTexObj texobj;
|
||||
GXColor background = {0, 0, 0, 0xff};
|
||||
static Mtx projectionMatrix,modelViewMatrix;
|
||||
void CheesyScale( unsigned char *XBuf );
|
||||
void CheesyScale(unsigned char *XBuf);
|
||||
int whichfb = 0;
|
||||
extern int font_height;
|
||||
int copynow = GX_FALSE;
|
||||
|
||||
extern int font_width;
|
||||
|
||||
int GetTextWidth( char *text )
|
||||
{
|
||||
int GetTextWidth(char *text) {
|
||||
unsigned int i, w = 0;
|
||||
|
||||
for ( i = 0; i < strlen(text); i++ )
|
||||
for (i = 0; i < strlen(text); i++)
|
||||
w += font_width;
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
int CentreTextPosition( char *text )
|
||||
{
|
||||
return ( ( 640 - GetTextWidth(text) ) >> 1 );
|
||||
int CentreTextPosition(char *text) {
|
||||
return ((640 - GetTextWidth(text)) >> 1);
|
||||
}
|
||||
|
||||
void WriteCentre( int y, char *text )
|
||||
{
|
||||
write_font( CentreTextPosition(text), y, text);
|
||||
void WriteCentre(int y, char *text) {
|
||||
write_font(CentreTextPosition(text), y, text);
|
||||
}
|
||||
|
||||
void WaitPrompt( char *msg )
|
||||
{
|
||||
void WaitPrompt(char *msg) {
|
||||
int quit = 0;
|
||||
|
||||
while ( PAD_ButtonsDown(0) & PAD_BUTTON_A ) {} ;
|
||||
|
||||
while( !(PAD_ButtonsDown(0) & PAD_BUTTON_A ) && (quit == 0 ))
|
||||
{
|
||||
while (PAD_ButtonsDown(0) & PAD_BUTTON_A) {} ;
|
||||
while(!(PAD_ButtonsDown(0) & PAD_BUTTON_A) && (quit == 0)) {
|
||||
ClearScreen();
|
||||
WriteCentre(220, msg);
|
||||
WriteCentre(220 + font_height, MENU_PRESS_A);
|
||||
|
||||
WriteCentre( 220, msg);
|
||||
WriteCentre( 220 + font_height, MENU_PRESS_A);
|
||||
|
||||
if ( PAD_ButtonsDown(0) & PAD_BUTTON_A )
|
||||
if (PAD_ButtonsDown(0) & PAD_BUTTON_A)
|
||||
quit = 1;
|
||||
|
||||
SetScreen();
|
||||
@ -88,18 +80,15 @@ void WaitPrompt( char *msg )
|
||||
/**
|
||||
* Wait for user to press A or B. Returns 0 = B; 1 = A
|
||||
*/
|
||||
int WaitButtonAB ()
|
||||
{
|
||||
int WaitButtonAB() {
|
||||
int btns;
|
||||
|
||||
while ( (PAD_ButtonsDown (0) & (PAD_BUTTON_A | PAD_BUTTON_B)) );
|
||||
|
||||
while ( TRUE )
|
||||
{
|
||||
while ((PAD_ButtonsDown (0) & (PAD_BUTTON_A | PAD_BUTTON_B)));
|
||||
while (1) {
|
||||
btns = PAD_ButtonsDown (0);
|
||||
if ( btns & PAD_BUTTON_A )
|
||||
if (btns & PAD_BUTTON_A)
|
||||
return 1;
|
||||
else if ( btns & PAD_BUTTON_B )
|
||||
else if (btns & PAD_BUTTON_B)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -108,8 +97,7 @@ int WaitButtonAB ()
|
||||
* Show a prompt with choice of two options. Returns 1 if A button was pressed
|
||||
and 0 if B button was pressed.
|
||||
*/
|
||||
int WaitPromptChoice (char *msg, char *bmsg, char *amsg)
|
||||
{
|
||||
int WaitPromptChoice(char *msg, char *bmsg, char *amsg) {
|
||||
char choiceOption[80];
|
||||
sprintf (choiceOption, "B = %s : A = %s", bmsg, amsg);
|
||||
|
||||
@ -121,20 +109,18 @@ int WaitPromptChoice (char *msg, char *bmsg, char *amsg)
|
||||
return WaitButtonAB ();
|
||||
}
|
||||
|
||||
void ShowAction( char *msg )
|
||||
{
|
||||
void ShowAction(char *msg) {
|
||||
memcpy (xfb[whichfb], &backdrop, 1280 * 480);
|
||||
/*ClearScreen();*/
|
||||
WriteCentre( 220 + ( font_height >> 1), msg);
|
||||
WriteCentre(220 + (font_height >> 1), msg);
|
||||
SetScreen();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* GX Chip Copy to XFB
|
||||
****************************************************************************/
|
||||
static void copy_to_xfb()
|
||||
{
|
||||
if ( copynow == GX_TRUE ) {
|
||||
static void copy_to_xfb() {
|
||||
if (copynow == GX_TRUE) {
|
||||
GX_CopyDisp(xfb[whichfb],GX_TRUE);
|
||||
GX_Flush();
|
||||
copynow = GX_FALSE;
|
||||
@ -144,9 +130,7 @@ static void copy_to_xfb()
|
||||
/****************************************************************************
|
||||
* Initialise the GX
|
||||
****************************************************************************/
|
||||
|
||||
void StartGX()
|
||||
{
|
||||
void StartGX() {
|
||||
/*** Clear out FIFO area ***/
|
||||
memset(&gp_fifo, 0, DEFAULT_FIFO_SIZE);
|
||||
|
||||
@ -205,24 +189,20 @@ void StartGX()
|
||||
*
|
||||
* Using the texture map draw with quads
|
||||
****************************************************************************/
|
||||
void GXDraw( unsigned char *XBuf )
|
||||
{
|
||||
|
||||
void GXDraw(unsigned char *XBuf) {
|
||||
float gs = 1.0;
|
||||
float gt = 1.0;
|
||||
int width, height,t,xb;
|
||||
unsigned short *texture;
|
||||
|
||||
memset(&texturemem, 0, TEX_WIDTH * TEX_HEIGHT * 2);
|
||||
texture = ( unsigned short *)&texturemem[ 16 * TEX_WIDTH ];
|
||||
texture = (unsigned short *)&texturemem[16 * TEX_WIDTH];
|
||||
|
||||
/*** Now draw the texture ***/
|
||||
t = 0;
|
||||
for ( height = 0; height < 120; height++ )
|
||||
{
|
||||
for(height = 0; height < 120; height++) {
|
||||
xb = height * 512;
|
||||
for( width = 256; width > 0; width -= 4 )
|
||||
{
|
||||
for(width = 256; width > 0; width -= 4) {
|
||||
/*** Row one ***/
|
||||
texture[t++] = rgb565[XBuf[xb + width-1]];
|
||||
texture[t++] = rgb565[XBuf[xb + width-2]];
|
||||
@ -246,9 +226,7 @@ void GXDraw( unsigned char *XBuf )
|
||||
texture[t++] = rgb565[XBuf[xb + 256 + width-2]];
|
||||
texture[t++] = rgb565[XBuf[xb + 256 + width-3]];
|
||||
texture[t++] = rgb565[XBuf[xb + 256 + width-4]];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DCFlushRange(&texturemem, TEX_WIDTH * TEX_HEIGHT * 2);
|
||||
@ -274,7 +252,6 @@ void GXDraw( unsigned char *XBuf )
|
||||
GX_End();
|
||||
GX_DrawDone();
|
||||
copynow = GX_TRUE;
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -289,41 +266,13 @@ void initDisplay() {
|
||||
/*** Start VIDEO Subsystem ***/
|
||||
VIDEO_Init();
|
||||
|
||||
extern GXRModeObj TVEurgb60Hz480IntDf;
|
||||
/*** Determine display mode
|
||||
NOTE: Force 60Hz 640x480 for PAL or NTSC ***/
|
||||
|
||||
switch(VIDEO_GetCurrentTvMode())
|
||||
{
|
||||
case VI_NTSC:
|
||||
vmode = &TVNtsc480IntDf;
|
||||
break;
|
||||
case VI_PAL:
|
||||
vmode = &TVPal574IntDfScale;
|
||||
break;
|
||||
#ifdef FORCE_EURGB60
|
||||
default:
|
||||
vmode = &TVEurgb60Hz480IntDf;
|
||||
break;
|
||||
#else
|
||||
case VI_MPAL:
|
||||
vmode = &TVMpal480IntDf;
|
||||
break;
|
||||
default:
|
||||
vmode = &TVNtsc480IntDf;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
//vmode = &TVPal528IntDf;
|
||||
|
||||
// works for NTSC and PAL on GC and Wii :)
|
||||
//vmode = &TVNtsc480IntDf;
|
||||
vmode = VIDEO_GetPreferredMode(NULL);
|
||||
VIDEO_Configure(vmode);
|
||||
|
||||
xfb[0] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(vmode));
|
||||
xfb[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(vmode));
|
||||
/*init_font();*/
|
||||
|
||||
VIDEO_Configure(vmode);
|
||||
VIDEO_SetNextFramebuffer(xfb[0]);
|
||||
VIDEO_SetBlack(FALSE);
|
||||
VIDEO_Flush();
|
||||
@ -337,7 +286,6 @@ NOTE: Force 60Hz 640x480 for PAL or NTSC ***/
|
||||
|
||||
PAD_Init();
|
||||
StartGX();
|
||||
DVD_Init();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -347,43 +295,37 @@ NOTE: Force 60Hz 640x480 for PAL or NTSC ***/
|
||||
****************************************************************************/
|
||||
#define NESWIDTH 256
|
||||
#define NESHEIGHT 240
|
||||
void RenderFrame( char *XBuf, int style )
|
||||
{
|
||||
|
||||
void RenderFrame(char *XBuf, int style) {
|
||||
int gcdispOffset = 32; /*** Offset to centre on screen ***/
|
||||
int w,h;
|
||||
int c,i;
|
||||
|
||||
whichfb ^= 1;
|
||||
|
||||
switch( style ) {
|
||||
|
||||
switch(style) {
|
||||
case 0 :
|
||||
VIDEO_ClearFrameBuffer( vmode, xfb[whichfb], COLOR_BLACK);
|
||||
VIDEO_ClearFrameBuffer(vmode, xfb[whichfb], COLOR_BLACK);
|
||||
|
||||
/*** Simply go through each row ***/
|
||||
for( h = 0; h < NESHEIGHT; h++ )
|
||||
{
|
||||
for( w = 0; w < NESWIDTH; w++ )
|
||||
{
|
||||
c = ( h << 8 ) + w;
|
||||
for(h = 0; h < NESHEIGHT; h++) {
|
||||
for(w = 0; w < NESWIDTH; w++) {
|
||||
c = (h << 8) + w;
|
||||
i = gcdispOffset + w;
|
||||
/*** Fast Zoom - Repeat each row, use 1 Xbuf == 2 GC
|
||||
To speed up more, use indexed palette array ***/
|
||||
|
||||
xfb[whichfb][i] = gcpalette[ (unsigned char)XBuf[ c ] ];
|
||||
xfb[whichfb][i + 320] = gcpalette[ (unsigned char)XBuf[ c ] ];
|
||||
xfb[whichfb][i] = gcpalette[(unsigned char)XBuf[c]];
|
||||
xfb[whichfb][i + 320] = gcpalette[(unsigned char)XBuf[c]];
|
||||
}
|
||||
gcdispOffset += 640;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
CheesyScale( XBuf );
|
||||
CheesyScale(XBuf);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
GXDraw( XBuf );
|
||||
GXDraw(XBuf);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -399,9 +341,8 @@ void RenderFrame( char *XBuf, int style )
|
||||
* Support routine for gcpalette
|
||||
****************************************************************************/
|
||||
|
||||
unsigned int rgbcolor( unsigned char r1, unsigned char g1, unsigned char b1,
|
||||
unsigned char r2, unsigned char g2, unsigned char b2)
|
||||
{
|
||||
unsigned int rgbcolor(unsigned char r1, unsigned char g1, unsigned char b1,
|
||||
unsigned char r2, unsigned char g2, unsigned char b2) {
|
||||
int y1,cb1,cr1,y2,cb2,cr2,cb,cr;
|
||||
|
||||
y1=(299*r1+587*g1+114*b1)/1000;
|
||||
@ -415,7 +356,7 @@ unsigned int rgbcolor( unsigned char r1, unsigned char g1, unsigned char b1,
|
||||
cb=(cb1+cb2) >> 1;
|
||||
cr=(cr1+cr2) >> 1;
|
||||
|
||||
return ( (y1 << 24) | (cb << 16) | (y2 << 8) | cr );
|
||||
return ((y1 << 24) | (cb << 16) | (y2 << 8) | cr);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -424,8 +365,8 @@ unsigned int rgbcolor( unsigned char r1, unsigned char g1, unsigned char b1,
|
||||
* A shadow copy of the palette is maintained, in case the NES Emu kernel
|
||||
* requests a copy.
|
||||
****************************************************************************/
|
||||
void FCEUD_SetPalette(unsigned char index, unsigned char r, unsigned char g, unsigned char b)
|
||||
{
|
||||
void FCEUD_SetPalette(unsigned char index, unsigned char r, unsigned char g,
|
||||
unsigned char b) {
|
||||
/*** Make PC compatible copy ***/
|
||||
pcpalette[index].r = r;
|
||||
pcpalette[index].g = g;
|
||||
@ -435,16 +376,16 @@ void FCEUD_SetPalette(unsigned char index, unsigned char r, unsigned char g, uns
|
||||
gcpalette[index] = rgbcolor(r,g,b,r,g,b);
|
||||
|
||||
/*** Generate RGB565 texture palette ***/
|
||||
rgb565[index] = ( ( r & 0xf8 ) << 8 ) |
|
||||
( ( g & 0xfc ) << 3 ) |
|
||||
( ( b & 0xf8 ) >> 3 );
|
||||
rgb565[index] = ((r & 0xf8) << 8) |
|
||||
((g & 0xfc) << 3) |
|
||||
((b & 0xf8) >> 3);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* GetPalette
|
||||
****************************************************************************/
|
||||
void FCEUD_GetPalette(unsigned char i, unsigned char *r, unsigned char *g, unsigned char *b)
|
||||
{
|
||||
void FCEUD_GetPalette(unsigned char i, unsigned char *r, unsigned char *g,
|
||||
unsigned char *b) {
|
||||
*r = pcpalette[i].r;
|
||||
*g = pcpalette[i].g;
|
||||
*b = pcpalette[i].b;
|
||||
@ -457,9 +398,7 @@ void FCEUD_GetPalette(unsigned char i, unsigned char *r, unsigned char *g, unsig
|
||||
* stretching the initial 256 pixels to 320.
|
||||
* The standard 2x2 scaler can then be applied
|
||||
****************************************************************************/
|
||||
void CheesyScale( unsigned char *XBuf )
|
||||
{
|
||||
|
||||
void CheesyScale(unsigned char *XBuf) {
|
||||
static int newrow[320]; /*** New cheesy row ***/
|
||||
unsigned int cheesypal[256]; /*** Enhanced Cheesy Palette ***/
|
||||
int i,j,c,p = 0;
|
||||
@ -468,23 +407,20 @@ void CheesyScale( unsigned char *XBuf )
|
||||
int h, n, nw;
|
||||
|
||||
/*** Stretch ***/
|
||||
for ( h = 0; h < NESHEIGHT; h++ )
|
||||
{
|
||||
for (h = 0; h < NESHEIGHT; h++) {
|
||||
j = c = p = 0;
|
||||
for ( i = 0; i < NESWIDTH; i++ )
|
||||
{
|
||||
|
||||
for (i = 0; i < NESWIDTH; i++) {
|
||||
/*** Every fifth pixel is stretched by adding
|
||||
the mid colour range ***/
|
||||
n = ( h << 8 ) + i;
|
||||
newrow[j++] = XBuf[ n ];
|
||||
n = (h << 8) + i;
|
||||
newrow[j++] = XBuf[n];
|
||||
c++;
|
||||
if ( c == 4 )
|
||||
{ /*** Done 4 pixels, so add the fifth ***/
|
||||
if (c == 4) { /*** Done 4 pixels, so add the fifth ***/
|
||||
p1 = XBuf[n];
|
||||
p2 = XBuf[n+1];
|
||||
cheesypal[p] = rgbcolor( pcpalette[p1].r, pcpalette[p1].g, pcpalette[p1].b,
|
||||
pcpalette[p2].r, pcpalette[p2].g, pcpalette[p2].b );
|
||||
cheesypal[p] = rgbcolor(pcpalette[p1].r, pcpalette[p1].g,
|
||||
pcpalette[p1].b, pcpalette[p2].r, pcpalette[p2].g,
|
||||
pcpalette[p2].b);
|
||||
newrow[j++] = 0x8000 + p;
|
||||
p++;
|
||||
c = 0;
|
||||
@ -494,22 +430,17 @@ void CheesyScale( unsigned char *XBuf )
|
||||
|
||||
/*** Now update the screen display with the new colours ***/
|
||||
ofs = gcdispOffset;
|
||||
for ( nw = 0; nw < 320; nw++ )
|
||||
{
|
||||
if ( newrow[nw] & 0x8000 ) {
|
||||
for (nw = 0; nw < 320; nw++) {
|
||||
if (newrow[nw] & 0x8000) {
|
||||
xfb[whichfb][ofs + nw] = cheesypal[newrow[nw] & 0xff ];
|
||||
xfb[whichfb][ofs + 320 + nw] = cheesypal[newrow[nw] & 0xff];
|
||||
}
|
||||
else
|
||||
{
|
||||
xfb[whichfb][ofs + nw] = gcpalette[ newrow[nw] ];
|
||||
xfb[whichfb][ofs + nw + 320] = gcpalette[ newrow[nw] ];
|
||||
} else {
|
||||
xfb[whichfb][ofs + nw] = gcpalette[newrow[nw]];
|
||||
xfb[whichfb][ofs + nw + 320] = gcpalette[newrow[nw]];
|
||||
}
|
||||
}
|
||||
|
||||
gcdispOffset += 640;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -15,23 +15,15 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
#include <sdcard.h>
|
||||
|
||||
#ifdef HW_RVL
|
||||
#include "wiisd/vfat.h"
|
||||
|
||||
extern VFATFS vfs;
|
||||
extern FSDIRENTRY vfsfile;
|
||||
extern u8 UseWiiSDCARD;
|
||||
#endif
|
||||
extern sd_file *filehandle;
|
||||
extern unsigned int dvd_read(void *dst, unsigned int len, u64 offset);
|
||||
extern FILE *filehandle;
|
||||
extern u8 UseSDCARD;
|
||||
|
||||
extern void ShowAction( char *msg );
|
||||
extern void WaitPrompt( char *msg );
|
||||
|
||||
extern unsigned char readbuffer[2048];
|
||||
extern unsigned int dvd_read(void *dst, unsigned int len, u64 offset);
|
||||
|
||||
#define ZIPCHUNK 2048
|
||||
|
||||
@ -51,8 +43,7 @@ typedef struct {
|
||||
unsigned short extraDataLength __attribute__ ((__packed__));
|
||||
} PKZIPHEADER;
|
||||
|
||||
static inline u32 FLIP32(u32 b)
|
||||
{
|
||||
static inline u32 FLIP32(u32 b) {
|
||||
unsigned int c;
|
||||
|
||||
c = ( b & 0xff000000 ) >> 24;
|
||||
@ -63,8 +54,7 @@ static inline u32 FLIP32(u32 b)
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline u16 FLIP16(u16 b)
|
||||
{
|
||||
static inline u16 FLIP16(u16 b) {
|
||||
u16 c;
|
||||
|
||||
c = ( b & 0xff00 ) >> 8;
|
||||
@ -83,12 +73,11 @@ static inline u16 FLIP16(u16 b)
|
||||
* it is populated before calling.
|
||||
****************************************************************************/
|
||||
|
||||
bool isZipFile()
|
||||
{
|
||||
bool isZipFile() {
|
||||
u32 check;
|
||||
|
||||
memcpy(&check, &readbuffer, 4);
|
||||
return ( check == PKZIPID ) ? true : false;
|
||||
return (check == PKZIPID) ? true : false;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -99,9 +88,8 @@ bool isZipFile()
|
||||
*
|
||||
* Unzip terminates on Z_END_STREAM.
|
||||
***************************************************************************/
|
||||
int unzipDVDFile( unsigned char *outbuffer,
|
||||
unsigned int discoffset, unsigned int length)
|
||||
{
|
||||
int unzipDVDFile(unsigned char *outbuffer,
|
||||
unsigned int discoffset, unsigned int length) {
|
||||
PKZIPHEADER pkzip;
|
||||
int zipoffset = 0;
|
||||
int zipchunk = 0;
|
||||
@ -134,14 +122,12 @@ int unzipDVDFile( unsigned char *outbuffer,
|
||||
zipchunk = ZIPCHUNK - zipoffset;
|
||||
|
||||
/*** No do it! ***/
|
||||
do
|
||||
{
|
||||
do {
|
||||
zs.avail_in = zipchunk;
|
||||
zs.next_in = (Bytef *)&readbuffer[zipoffset];
|
||||
|
||||
/*** Now inflate until input buffer is exhausted ***/
|
||||
do
|
||||
{
|
||||
do {
|
||||
zs.avail_out = ZIPCHUNK;
|
||||
zs.next_out = (Bytef *)&out;
|
||||
|
||||
@ -153,7 +139,7 @@ int unzipDVDFile( unsigned char *outbuffer,
|
||||
}
|
||||
|
||||
have = ZIPCHUNK - zs.avail_out;
|
||||
if ( have ) {
|
||||
if (have) {
|
||||
/*** Copy to normal block buffer ***/
|
||||
memcpy(&outbuffer[bufferoffset], &out, have);
|
||||
bufferoffset += have;
|
||||
@ -165,23 +151,13 @@ int unzipDVDFile( unsigned char *outbuffer,
|
||||
zipoffset = 0;
|
||||
zipchunk = ZIPCHUNK;
|
||||
discoffset += 2048;
|
||||
if ( UseSDCARD )
|
||||
SDCARD_ReadFile(filehandle, &readbuffer, 2048);
|
||||
#ifdef HW_RVL
|
||||
else if (UseWiiSDCARD) VFAT_fread(&vfsfile, &readbuffer, 2048);
|
||||
#endif
|
||||
else
|
||||
dvd_read(&readbuffer, 2048, discoffset);
|
||||
|
||||
if (UseSDCARD) fread(&readbuffer, 2048, 1, filehandle);
|
||||
else dvd_read(&readbuffer, 2048, discoffset);
|
||||
} while ( res != Z_STREAM_END );
|
||||
|
||||
inflateEnd(&zs);
|
||||
|
||||
if ( UseSDCARD )
|
||||
SDCARD_CloseFile(filehandle);
|
||||
#ifdef HW_RVL
|
||||
else if (UseWiiSDCARD) VFAT_fclose(&vfsfile);
|
||||
#endif
|
||||
if (UseSDCARD) fclose(filehandle);
|
||||
|
||||
if ( res == Z_STREAM_END ) {
|
||||
if ( FLIP32(pkzip.uncompressedSize == (u32)bufferoffset ) )
|
||||
|
@ -41,14 +41,11 @@ extern char backdrop[640 * 480 * 2];
|
||||
extern u8 UseSDCARD;
|
||||
extern int scrollerx;
|
||||
|
||||
#ifdef HW_RVL
|
||||
void (*Reload)() = (void(*)())0x90000020;
|
||||
#else
|
||||
void (*Reload)() = (void(*)())0x80001800;
|
||||
#endif
|
||||
//void (*Reload)() = (void(*)())0x80001800;
|
||||
void Reload() { exit(0); }
|
||||
|
||||
void Reboot() {
|
||||
#ifdef HW_RVL
|
||||
#ifdef __wii__
|
||||
// Thanks to eke-eke
|
||||
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
|
||||
#else
|
||||
@ -555,22 +552,18 @@ void ConfigPAD() {
|
||||
/****************************************************************************
|
||||
* Save Game Manager
|
||||
****************************************************************************/
|
||||
int SdSlotCount = 3;
|
||||
char SdSlots[3][10] = {
|
||||
{ "Slot A" }, { "Slot B" }, { "Wii SD"}
|
||||
int SdSlotCount = 2;
|
||||
char SdSlots[2][10] = {
|
||||
{ "Slot A" }, { "Slot B" }
|
||||
};
|
||||
enum SLOTS {
|
||||
SLOT_A, SLOT_B, SLOT_WIISD
|
||||
SLOT_A, SLOT_B
|
||||
};
|
||||
enum DEVICES {
|
||||
MEMCARD, SDCARD
|
||||
};
|
||||
|
||||
#ifdef HW_RVL
|
||||
u8 ChosenSlot = SLOT_WIISD;
|
||||
#else
|
||||
u8 ChosenSlot = SLOT_A;
|
||||
#endif
|
||||
u8 ChosenDevice = SDCARD;
|
||||
|
||||
int StateManager() {
|
||||
@ -591,7 +584,10 @@ int StateManager() {
|
||||
{ MENU_SAVE_TEXT2 }
|
||||
};
|
||||
|
||||
|
||||
#ifdef __wii__
|
||||
strcpy(SaveMenu[SAVE_SLOT], SaveMenu[SAVE_EXIT]);
|
||||
SaveMenuCount--;
|
||||
#endif
|
||||
int ChosenMenu = 0;
|
||||
int quit = 0;
|
||||
short j;
|
||||
@ -602,8 +598,10 @@ int StateManager() {
|
||||
|
||||
while ( quit == 0 ) {
|
||||
if ( redraw ) {
|
||||
#ifdef __gamecube__
|
||||
sprintf(SaveMenu[SAVE_SLOT], "%s: %s", (ChosenDevice == SDCARD) ? "SDCard" : "MemCard",
|
||||
SdSlots[ChosenSlot]);
|
||||
#endif
|
||||
sprintf(SaveMenu[SAVE_DEVICE], MENU_SAVE_DEVICE ": %s", (ChosenDevice == SDCARD) ? "SDCard" : "MemCard");
|
||||
DrawMenu(MENU_SAVE_TITLE, SaveMenu, SaveMenuCount, ChosenMenu);
|
||||
redraw = 0;
|
||||
@ -633,10 +631,12 @@ int StateManager() {
|
||||
ChosenDevice ^= 1;
|
||||
break;
|
||||
case SAVE_SLOT:
|
||||
#ifdef __gamecube__
|
||||
ChosenSlot++;
|
||||
if (ChosenSlot >= SdSlotCount)
|
||||
ChosenSlot = 0;
|
||||
break;
|
||||
#endif
|
||||
case SAVE_EXIT:
|
||||
quit = 1;
|
||||
break;
|
||||
@ -646,23 +646,29 @@ int StateManager() {
|
||||
}
|
||||
|
||||
if (j & PAD_BUTTON_RIGHT) {
|
||||
#ifdef __gamecube__
|
||||
if (ChosenMenu == SAVE_SLOT) {
|
||||
ChosenSlot++;
|
||||
if (ChosenSlot >= SdSlotCount)
|
||||
ChosenSlot = SdSlotCount - 1;
|
||||
redraw = 1;
|
||||
} else if (ChosenMenu == SAVE_DEVICE) {
|
||||
}
|
||||
#endif
|
||||
if (ChosenMenu == SAVE_DEVICE) {
|
||||
if (ChosenDevice == 0) ChosenDevice = 1;
|
||||
redraw = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (j & PAD_BUTTON_LEFT) {
|
||||
#ifdef __gamecube__
|
||||
if (ChosenMenu == SAVE_SLOT) {
|
||||
if (ChosenSlot)
|
||||
ChosenSlot--;
|
||||
redraw = 1;
|
||||
} else if (ChosenMenu == SAVE_DEVICE) {
|
||||
}
|
||||
#endif
|
||||
if (ChosenMenu == SAVE_DEVICE) {
|
||||
if (ChosenDevice) ChosenDevice = 0;
|
||||
redraw = 1;
|
||||
}
|
||||
@ -959,11 +965,10 @@ int MediaSelect() {
|
||||
line = 0;
|
||||
scrollerx = 320 - MARGIN;
|
||||
|
||||
#ifdef HW_RVL
|
||||
strcpy(MediaMenu[MEDIA_DVD], MediaMenu[MEDIA_EXIT]);
|
||||
MediaMenuCount = 3;
|
||||
#else
|
||||
SdSlotCount = 2;
|
||||
#ifdef __wii__
|
||||
// bypass all this in Wii mode
|
||||
OpenSD();
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
while ( quit == 0 ) {
|
||||
@ -988,41 +993,27 @@ int MediaSelect() {
|
||||
redraw = 1;
|
||||
switch ( ChosenMenu ) {
|
||||
case MEDIA_SDCARD:
|
||||
#ifdef HW_RVL
|
||||
if (ChosenSlot == SLOT_WIISD) {
|
||||
OpenWiiSD();
|
||||
} else
|
||||
#endif
|
||||
OpenSD();
|
||||
return 1;
|
||||
break;
|
||||
OpenSD();
|
||||
return 1;
|
||||
break;
|
||||
case MEDIA_SLOT:
|
||||
ChosenSlot++;
|
||||
if (ChosenSlot >= SdSlotCount)
|
||||
ChosenSlot = 0;
|
||||
redraw = 1;
|
||||
break;
|
||||
ChosenSlot ^= 1;
|
||||
redraw = 1;
|
||||
break;
|
||||
case MEDIA_DVD:
|
||||
#ifdef HW_RVL
|
||||
// In Wii mode, this is just exit
|
||||
quit = 1;
|
||||
#else
|
||||
UseSDCARD = 0; //DVD
|
||||
OpenDVD();
|
||||
ChosenDevice = 1; // Memcard
|
||||
return 1;
|
||||
#endif
|
||||
break;
|
||||
#ifndef HW_RVL
|
||||
UseSDCARD = 0; //DVD
|
||||
OpenDVD();
|
||||
ChosenDevice = 1; // Memcard
|
||||
return 1;
|
||||
break;
|
||||
case MEDIA_STOPDVD:
|
||||
ShowAction((char*)MENU_MEDIA_STOPPING);
|
||||
dvd_motor_off();
|
||||
WaitPrompt((char*)MENU_MEDIA_STOPPED);
|
||||
ShowAction((char*)MENU_MEDIA_STOPPING);
|
||||
dvd_motor_off();
|
||||
WaitPrompt((char*)MENU_MEDIA_STOPPED);
|
||||
break;
|
||||
case MEDIA_EXIT:
|
||||
quit = 1;
|
||||
break;
|
||||
#endif
|
||||
|
||||
quit = 1;
|
||||
break;
|
||||
default: break ;
|
||||
}
|
||||
}
|
||||
|
@ -70,18 +70,12 @@ int main(int argc, char *argv[]) {
|
||||
SYS_SetResetCallback(reset_cb);
|
||||
//SYS_SetPowerCallback(power_cb);
|
||||
InitialiseSound();
|
||||
SDCARD_Init ();
|
||||
|
||||
int driveid = -1;
|
||||
|
||||
/*** Get Drive Type ***/
|
||||
fatInitDefault();
|
||||
#ifdef __gamecube__
|
||||
DVD_Init();
|
||||
dvd_inquiry();
|
||||
driveid = (int)inquiry[2];
|
||||
|
||||
/*** Make sure it's one I now about ***/
|
||||
if ( ( driveid != 4 ) && ( driveid != 6 ) && ( driveid != 8 ) ) {
|
||||
isWii = true;
|
||||
}
|
||||
#endif
|
||||
DEBUG_Init(0, 1);
|
||||
|
||||
/*** Minimal Emulation Loop ***/
|
||||
if ( !FCEUI_Initialize() ) {
|
||||
|
@ -7,19 +7,13 @@
|
||||
****************************************************************************/
|
||||
#include <gccore.h>
|
||||
#include <string.h>
|
||||
#include <sdcard.h>
|
||||
#include <malloc.h>
|
||||
#include <fat.h>
|
||||
#include "../../types.h"
|
||||
#include "../../state.h"
|
||||
#include "saveicon.h"
|
||||
#include "intl.h"
|
||||
|
||||
#ifdef HW_RVL
|
||||
#include "wiisd/tff.h"
|
||||
#include "wiisd/integer.h"
|
||||
FATFS frontfs;
|
||||
FILINFO finfo;
|
||||
#endif
|
||||
#define FCEUDIR "fceu"
|
||||
#define SAVEDIR "saves"
|
||||
|
||||
@ -73,21 +67,18 @@ extern struct st_palettes {
|
||||
****************************************************************************/
|
||||
|
||||
/*** Open a file ***/
|
||||
void memopen()
|
||||
{
|
||||
void memopen() {
|
||||
sboffset = 0;
|
||||
memset(&statebuffer[0], 0, sizeof(statebuffer));
|
||||
memset(statebuffer, 0, sizeof(statebuffer));
|
||||
}
|
||||
|
||||
/*** Close a file ***/
|
||||
void memclose()
|
||||
{
|
||||
void memclose() {
|
||||
sboffset = 0;
|
||||
}
|
||||
|
||||
/*** Write to the file ***/
|
||||
void memfwrite( void *buffer, int len )
|
||||
{
|
||||
void memfwrite( void *buffer, int len ) {
|
||||
if ( (sboffset + len ) > sizeof(statebuffer))
|
||||
WaitPrompt("Buffer Exceeded");
|
||||
|
||||
@ -98,8 +89,7 @@ void memfwrite( void *buffer, int len )
|
||||
}
|
||||
|
||||
/*** Read from a file ***/
|
||||
void memfread( void *buffer, int len )
|
||||
{
|
||||
void memfread( void *buffer, int len ) {
|
||||
|
||||
if ( ( sboffset + len ) > sizeof(statebuffer))
|
||||
WaitPrompt("Buffer exceeded");
|
||||
@ -115,9 +105,7 @@ void memfread( void *buffer, int len )
|
||||
*
|
||||
* Read the array of SFORMAT structures to memory
|
||||
****************************************************************************/
|
||||
|
||||
int GCReadChunk( int chunkid, SFORMAT *sf )
|
||||
{
|
||||
int GCReadChunk( int chunkid, SFORMAT *sf ) {
|
||||
int csize;
|
||||
static char chunk[6];
|
||||
int chunklength;
|
||||
@ -128,22 +116,17 @@ int GCReadChunk( int chunkid, SFORMAT *sf )
|
||||
memfread(&thischunk, 4);
|
||||
memfread(&chunklength, 4);
|
||||
|
||||
if ( strcmp(chunk, "CHNK") == 0 )
|
||||
{
|
||||
if ( chunkid == thischunk )
|
||||
{
|
||||
if (strcmp(chunk, "CHNK") == 0) {
|
||||
if (chunkid == thischunk) {
|
||||
/*** Now decode the array of chunks to this one ***/
|
||||
while ( sf->v )
|
||||
{
|
||||
while (sf->v) {
|
||||
memfread(&chunk, 4);
|
||||
if ( memcmp(&chunk, "CHKE", 4) == 0 )
|
||||
return 1;
|
||||
|
||||
if ( memcmp(&chunk, sf->desc, 4) == 0 )
|
||||
{
|
||||
if (memcmp(&chunk, sf->desc, 4) == 0) {
|
||||
memfread(&csize, 4);
|
||||
if ( csize == ( sf->s & ( ~RLSB ) ) )
|
||||
{
|
||||
if (csize == (sf->s & (~RLSB ))) {
|
||||
memfread( sf->v, csize );
|
||||
sprintf(info,"%s %d", chunk, csize);
|
||||
} else {
|
||||
@ -155,11 +138,9 @@ int GCReadChunk( int chunkid, SFORMAT *sf )
|
||||
WaitPrompt(info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sf++;
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
} else
|
||||
return 0;
|
||||
} else
|
||||
return 0;
|
||||
@ -172,9 +153,7 @@ int GCReadChunk( int chunkid, SFORMAT *sf )
|
||||
*
|
||||
* Reads the SFORMAT arrays
|
||||
****************************************************************************/
|
||||
|
||||
int GCFCEUSS_Load()
|
||||
{
|
||||
int GCFCEUSS_Load() {
|
||||
int totalsize = 0;
|
||||
|
||||
sboffset = 16 + sizeof(saveicon) + 64; /*** Reset memory file pointer ***/
|
||||
@ -182,18 +161,12 @@ int GCFCEUSS_Load()
|
||||
memcpy(&totalsize, &statebuffer[FILESIZEOFFSET], 4);
|
||||
|
||||
/*** Now read the chunks back ***/
|
||||
if ( GCReadChunk( 1, SFCPU ) )
|
||||
{
|
||||
if ( GCReadChunk( 2, SFCPUC ) )
|
||||
{
|
||||
if ( GCReadChunk( 3, FCEUPPU_STATEINFO ) )
|
||||
{
|
||||
if ( GCReadChunk( 4, FCEUCTRL_STATEINFO ) )
|
||||
{
|
||||
if ( GCReadChunk( 5, FCEUSND_STATEINFO ) )
|
||||
{
|
||||
|
||||
if ( GCReadChunk( 0x10, SFMDATA ) )
|
||||
if (GCReadChunk(1, SFCPU)) {
|
||||
if (GCReadChunk(2, SFCPUC)) {
|
||||
if (GCReadChunk(3, FCEUPPU_STATEINFO)) {
|
||||
if (GCReadChunk(4, FCEUCTRL_STATEINFO)) {
|
||||
if (GCReadChunk(5, FCEUSND_STATEINFO)) {
|
||||
if (GCReadChunk(0x10, SFMDATA))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -202,7 +175,6 @@ int GCFCEUSS_Load()
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -210,8 +182,7 @@ int GCFCEUSS_Load()
|
||||
*
|
||||
* Write the array of SFORMAT structures to the file
|
||||
****************************************************************************/
|
||||
int GCSaveChunk( int chunkid, SFORMAT *sf )
|
||||
{
|
||||
int GCSaveChunk(int chunkid, SFORMAT *sf) {
|
||||
int chnkstart;
|
||||
int csize = 0;
|
||||
int chsize = 0;
|
||||
@ -225,8 +196,7 @@ int GCSaveChunk( int chunkid, SFORMAT *sf )
|
||||
csize += 12;
|
||||
|
||||
/*** Now run through this structure ***/
|
||||
while (sf->v)
|
||||
{
|
||||
while (sf->v) {
|
||||
/*** Check that there is a decription ***/
|
||||
if ( sf->desc == NULL)
|
||||
break;
|
||||
@ -261,8 +231,7 @@ int GCSaveChunk( int chunkid, SFORMAT *sf )
|
||||
* It uses memory for it's I/O and has an added CHNK block.
|
||||
* The file is terminated with CHNK length of 0.
|
||||
****************************************************************************/
|
||||
int GCFCEUSS_Save()
|
||||
{
|
||||
int GCFCEUSS_Save() {
|
||||
int totalsize = 0;
|
||||
static unsigned char header[16] = "FCS\xff";
|
||||
char chunk[] = "CHKE";
|
||||
@ -322,8 +291,7 @@ void CardRemoved(s32 chn,s32 result) {
|
||||
/****************************************************************************
|
||||
* Snes9xGX Memcard
|
||||
****************************************************************************/
|
||||
void uselessinquiry()
|
||||
{
|
||||
void uselessinquiry() {
|
||||
volatile long *udvd = ( volatile long *)0xCC006000;
|
||||
|
||||
udvd[0] = 0;
|
||||
@ -335,22 +303,19 @@ void uselessinquiry()
|
||||
udvd[6] = 0x20;
|
||||
udvd[7] = 1;
|
||||
|
||||
while ( udvd[7] & 1 );
|
||||
|
||||
while (udvd[7] & 1);
|
||||
}
|
||||
|
||||
int MountTheCard()
|
||||
{
|
||||
int MountTheCard() {
|
||||
int tries = 0;
|
||||
int CardError;
|
||||
while ( tries < 10 )
|
||||
{
|
||||
while (tries < 10) {
|
||||
*(unsigned long*)(0xcc006800) |= 1<<13; /*** Disable Encryption ***/
|
||||
uselessinquiry();
|
||||
VIDEO_WaitVSync();
|
||||
//CardError = CARD_Mount(CARDSLOT, SysArea, NULL); /*** Don't need or want a callback ***/
|
||||
CardError = CARD_Mount(CARDSLOT, SysArea, CardRemoved);
|
||||
if ( CardError == 0 )
|
||||
if (CardError == 0)
|
||||
return 0;
|
||||
else {
|
||||
EXI_ProbeReset();
|
||||
@ -388,18 +353,18 @@ void MC_ManageState(int mode, int slot) {
|
||||
/*** Try for memory card in slot A ***/
|
||||
CardError = MountTheCard();
|
||||
|
||||
if ( CardError >= 0 ) {
|
||||
if (CardError >= 0) {
|
||||
/*** Get card sector size ***/
|
||||
CardError = CARD_GetSectorSize(CARDSLOT, &SectorSize);
|
||||
|
||||
switch ( mode ) {
|
||||
switch (mode) {
|
||||
case 0 : { /*** Save Game ***/
|
||||
/*** Look for this file ***/
|
||||
CardError = CARD_FindFirst(CARDSLOT, &CardDir, true);
|
||||
|
||||
found = 0;
|
||||
card_stat CardStatus;
|
||||
while ( CardError != CARD_ERROR_NOFILE ) {
|
||||
while (CardError != CARD_ERROR_NOFILE) {
|
||||
CardError = CARD_FindNext(&CardDir);
|
||||
if ( strcmp(CardDir.filename, mcFilename) == 0 )
|
||||
found = 1;
|
||||
@ -411,26 +376,26 @@ void MC_ManageState(int mode, int slot) {
|
||||
ShowAction(debug);
|
||||
|
||||
FileSize = ( actualSize / SectorSize ) * SectorSize;
|
||||
if ( actualSize % SectorSize )
|
||||
if (actualSize % SectorSize)
|
||||
FileSize += SectorSize;
|
||||
|
||||
/*** Now write the file out ***/
|
||||
if ( !found )
|
||||
if (!found)
|
||||
CardError = CARD_Create(CARDSLOT, mcFilename, FileSize, &CardFile);
|
||||
else
|
||||
CardError = CARD_Open(CARDSLOT, mcFilename, &CardFile);
|
||||
|
||||
CARD_GetStatus( CARDSLOT, CardFile.filenum, &CardStatus);
|
||||
CARD_GetStatus(CARDSLOT, CardFile.filenum, &CardStatus);
|
||||
CardStatus.icon_addr = 0;
|
||||
CardStatus.icon_fmt = 2;
|
||||
CardStatus.icon_speed = 1;
|
||||
CardStatus.comment_addr = sizeof(saveicon);
|
||||
CARD_SetStatus( CARDSLOT, CardFile.filenum, &CardStatus);
|
||||
CARD_SetStatus(CARDSLOT, CardFile.filenum, &CardStatus);
|
||||
|
||||
/*** Haha! libogc only write one block at a time! ***/
|
||||
if ( CardError == 0 ) {
|
||||
if (CardError == 0) {
|
||||
int sbo = 0;
|
||||
while ( actualSize > 0 ) {
|
||||
while (actualSize > 0) {
|
||||
CardError = CARD_Write(&CardFile, &statebuffer[sbo], SectorSize, sbo );
|
||||
actualSize -= SectorSize;
|
||||
sbo += SectorSize;
|
||||
@ -439,8 +404,7 @@ void MC_ManageState(int mode, int slot) {
|
||||
CardError = CARD_Close(&CardFile);
|
||||
sprintf(debug, "Saved %d bytes successfully!", savedBytes);
|
||||
ShowAction(debug);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
WaitPrompt("Save Failed");
|
||||
}
|
||||
|
||||
@ -453,13 +417,13 @@ void MC_ManageState(int mode, int slot) {
|
||||
CardError = CARD_FindFirst(CARDSLOT, &CardDir, true);
|
||||
memopen(); /*** Clear the buffer ***/
|
||||
found = 0;
|
||||
while ( CardError != CARD_ERROR_NOFILE ) {
|
||||
while (CardError != CARD_ERROR_NOFILE) {
|
||||
CardError = CARD_FindNext(&CardDir);
|
||||
if ( strcmp(CardDir.filename, mcFilename) == 0 )
|
||||
if (strcmp(CardDir.filename, mcFilename) == 0)
|
||||
found = 1;
|
||||
}
|
||||
|
||||
if ( found == 0 ) {
|
||||
if (found == 0) {
|
||||
WaitPrompt("No Save Game Found");
|
||||
CARD_Unmount(CARDSLOT);
|
||||
return;
|
||||
@ -475,7 +439,7 @@ void MC_ManageState(int mode, int slot) {
|
||||
|
||||
int sbo = SectorSize;
|
||||
actualSize -= SectorSize;
|
||||
while( actualSize > 0 ) {
|
||||
while(actualSize > 0) {
|
||||
CARD_Read(&CardFile, &statebuffer[sbo], SectorSize, sbo);
|
||||
actualSize -= SectorSize;
|
||||
sbo += SectorSize;
|
||||
@ -501,161 +465,48 @@ void MC_ManageState(int mode, int slot) {
|
||||
void SD_ManageState(int mode, int slot) {
|
||||
char path[1024];
|
||||
char msg[128];
|
||||
int offset = 0;
|
||||
int filesize = 0;
|
||||
int len = 0;
|
||||
int offset = 0;
|
||||
FILE *handle;
|
||||
|
||||
if (slot < 2) {
|
||||
sd_file *handle;
|
||||
sprintf (path, "dev%d:\\%s\\%s\\%08x.fcs", ChosenSlot, FCEUDIR, SAVEDIR, iNESGameCRC32);
|
||||
if (mode == 0) ShowAction ("Saving STATE to SD...");
|
||||
else ShowAction ("Loading STATE from SD...");
|
||||
|
||||
if (mode == 0) ShowAction ("Saving STATE to SD...");
|
||||
else ShowAction ("Loading STATE from SD...");
|
||||
sprintf (path, "/%s/%s/%08x.fcs", FCEUDIR, SAVEDIR, iNESGameCRC32);
|
||||
handle = fopen(path, (mode == 0) ? "wb" : "rb");
|
||||
|
||||
handle = SDCARD_OpenFile(path, (mode == 0) ? "wb" : "rb");
|
||||
if (handle == NULL) {
|
||||
sprintf(msg, "Couldn't open %s", path);
|
||||
WaitPrompt(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (handle == NULL){
|
||||
sprintf(msg, "Couldn't open %s", path);
|
||||
WaitPrompt(msg);
|
||||
return;
|
||||
}
|
||||
if (mode == 0) { //Save
|
||||
filesize = GCFCEUSS_Save();
|
||||
|
||||
if (mode == 0){ //Save
|
||||
filesize = GCFCEUSS_Save();
|
||||
len = fwrite(statebuffer, filesize, 1, handle);
|
||||
fclose(handle);
|
||||
|
||||
len = SDCARD_WriteFile (handle, statebuffer, filesize);
|
||||
SDCARD_CloseFile (handle);
|
||||
|
||||
if (len != filesize){
|
||||
sprintf (msg, "Error writing %s", path);
|
||||
WaitPrompt (msg);
|
||||
return;
|
||||
}
|
||||
|
||||
sprintf (msg, "Saved %d bytes successfully", filesize);
|
||||
if (len != filesize){
|
||||
sprintf (msg, "Error writing %s", path);
|
||||
WaitPrompt (msg);
|
||||
}
|
||||
else{ //Load
|
||||
|
||||
memopen();
|
||||
while ((len = SDCARD_ReadFile (handle, &statebuffer[offset], 1024)) > 0) offset += len;
|
||||
SDCARD_CloseFile (handle);
|
||||
|
||||
sprintf (msg, "Loaded %d bytes successfully", offset);
|
||||
ShowAction(msg);
|
||||
|
||||
GCFCEUSS_Load();
|
||||
return ;
|
||||
}
|
||||
} else { // WiiSD
|
||||
#ifdef HW_RVL
|
||||
if (mode == 0) ShowAction ("Saving State to WiiSD...");
|
||||
else ShowAction ("Loading State from WiiSD...");
|
||||
|
||||
sprintf(path, "/%s/%s/%08X.fcs", FCEUDIR, SAVEDIR, iNESGameCRC32);
|
||||
FIL fp;
|
||||
int res;
|
||||
u32 offset = 0;
|
||||
|
||||
/* Mount WiiSD with TinyFatFS*/
|
||||
if(f_mount(0, &frontfs) != FR_OK) {
|
||||
WaitPrompt((char*)"f_mount failed");
|
||||
return 0;
|
||||
}
|
||||
memset(&finfo, 0, sizeof(finfo));
|
||||
|
||||
if (mode == 0)
|
||||
res = f_open(&fp, path, FA_CREATE_ALWAYS | FA_WRITE);
|
||||
else {
|
||||
if ((res=f_stat(path, &finfo)) != FR_OK) {
|
||||
if (res == FR_NO_FILE) {
|
||||
sprintf(msg, "Unable to find %s.", path);
|
||||
}
|
||||
else {
|
||||
sprintf(msg, "f_stat failed, error %d", res);
|
||||
}
|
||||
WaitPrompt(msg);
|
||||
return;
|
||||
}
|
||||
res = f_open(&fp, path, FA_READ);
|
||||
return;
|
||||
}
|
||||
|
||||
if (res != FR_OK) {
|
||||
sprintf(msg, "Failed to open %s, error %d.", path, res);
|
||||
WaitPrompt(msg);
|
||||
return;
|
||||
}
|
||||
sprintf (msg, "Saved %d bytes successfully", filesize);
|
||||
WaitPrompt (msg);
|
||||
} else { //Load
|
||||
memopen();
|
||||
while ((len = fread(&statebuffer[offset], 1, 1024, handle)) > 0)
|
||||
offset += len;
|
||||
fclose(handle);
|
||||
|
||||
if (mode == 0) { // Save
|
||||
u32 written = 0, total_written = 0;
|
||||
sprintf (msg, "Loaded %d bytes successfully", offset);
|
||||
ShowAction(msg);
|
||||
|
||||
filesize = GCFCEUSS_Save();
|
||||
sprintf(msg, "Writing %d bytes..", filesize);
|
||||
ShowAction(msg);
|
||||
|
||||
offset = filesize;
|
||||
// Can only write 64k at a time
|
||||
while (offset > 65000) {
|
||||
if ((res = f_write(&fp, &statebuffer[total_written], 65000, &written)) != FR_OK) {
|
||||
sprintf(msg, "f_write failed, error %d", res);
|
||||
WaitPrompt(msg);
|
||||
f_close(&fp);
|
||||
return;
|
||||
}
|
||||
offset -= written;
|
||||
total_written += written;
|
||||
}
|
||||
// Write last 64k
|
||||
if ((res = f_write(&fp, statebuffer+total_written, offset, &written)) != FR_OK) {
|
||||
sprintf(msg, "f_write failed, error %d", res);
|
||||
WaitPrompt(msg);
|
||||
f_close(&fp);
|
||||
return;
|
||||
}
|
||||
offset -= written;
|
||||
total_written += written;
|
||||
if (total_written == filesize) {
|
||||
sprintf(msg, "Wrote %d bytes.", total_written);
|
||||
ShowAction(msg);
|
||||
f_close(&fp);
|
||||
return;
|
||||
}
|
||||
|
||||
sprintf(msg, "Write size mismatch, %d of %d bytes", written, filesize);
|
||||
WaitPrompt(msg);
|
||||
sprintf(msg, "Unable to save %s", path);
|
||||
WaitPrompt(msg);
|
||||
f_close(&fp);
|
||||
return;
|
||||
} else { // Load
|
||||
u32 bytes_read = 0, bytes_read_total = 0;
|
||||
|
||||
memopen();
|
||||
while(bytes_read_total < finfo.fsize) {
|
||||
if (f_read(&fp, &statebuffer[bytes_read_total], 0x200, &bytes_read) != FR_OK) {
|
||||
WaitPrompt((char*)"f_read failed");
|
||||
f_close(&fp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bytes_read == 0)
|
||||
break;
|
||||
bytes_read_total += bytes_read;
|
||||
}
|
||||
|
||||
if (bytes_read_total < finfo.fsize) {
|
||||
WaitPrompt((char*)"read failed");
|
||||
f_close(&fp);
|
||||
return;
|
||||
}
|
||||
sprintf(msg, "Read %d of %ld bytes.", bytes_read_total, finfo.fsize);
|
||||
ShowAction(msg);
|
||||
f_close(&fp);
|
||||
offset = bytes_read_total;
|
||||
GCFCEUSS_Load();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
GCFCEUSS_Load();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -767,18 +618,18 @@ void MC_ManageSettings(int mode, int slot, int quiet) {
|
||||
/*** Try for memory card in slot A ***/
|
||||
CardError = MountTheCard();
|
||||
|
||||
if ( CardError >= 0 ) {
|
||||
if (CardError >= 0) {
|
||||
/*** Get card sector size ***/
|
||||
CardError = CARD_GetSectorSize(slot, &SectorSize);
|
||||
|
||||
switch ( mode ) {
|
||||
switch (mode) {
|
||||
case 0 : { /*** Save Game ***/
|
||||
/*** Look for this file ***/
|
||||
CardError = CARD_FindFirst(slot, &CardDir, true);
|
||||
|
||||
found = 0;
|
||||
card_stat CardStatus;
|
||||
while ( CardError != CARD_ERROR_NOFILE ) {
|
||||
while (CardError != CARD_ERROR_NOFILE) {
|
||||
CardError = CARD_FindNext(&CardDir);
|
||||
if ( strcmp(CardDir.filename, mcFilename) == 0 )
|
||||
found = 1;
|
||||
@ -793,27 +644,27 @@ void MC_ManageSettings(int mode, int slot, int quiet) {
|
||||
sprintf(msg, "Saving Settings to MC ...");
|
||||
ShowAction(msg);
|
||||
|
||||
FileSize = ( actualSize / SectorSize ) * SectorSize;
|
||||
if ( (actualSize % SectorSize) || (FileSize == 0) )
|
||||
FileSize = (actualSize / SectorSize) * SectorSize;
|
||||
if ((actualSize % SectorSize) || (FileSize == 0))
|
||||
FileSize += SectorSize;
|
||||
|
||||
/*** Now write the file out ***/
|
||||
if ( !found )
|
||||
if (!found)
|
||||
CardError = CARD_Create(CARDSLOT, mcFilename, FileSize, &CardFile);
|
||||
else
|
||||
CardError = CARD_Open(CARDSLOT, mcFilename, &CardFile);
|
||||
|
||||
CARD_GetStatus( CARDSLOT, CardFile.filenum, &CardStatus);
|
||||
CARD_GetStatus(CARDSLOT, CardFile.filenum, &CardStatus);
|
||||
CardStatus.icon_addr = 0;
|
||||
CardStatus.icon_fmt = 2;
|
||||
CardStatus.icon_speed = 1;
|
||||
CardStatus.comment_addr = sizeof(saveicon);
|
||||
CARD_SetStatus( CARDSLOT, CardFile.filenum, &CardStatus);
|
||||
CARD_SetStatus(CARDSLOT, CardFile.filenum, &CardStatus);
|
||||
|
||||
/*** Haha! libogc only write one block at a time! ***/
|
||||
if ( CardError == 0 ) {
|
||||
if (CardError == 0) {
|
||||
int sbo = 0;
|
||||
while ( actualSize > 0 ) {
|
||||
while (actualSize > 0) {
|
||||
CardError = CARD_Write(&CardFile, &buffer[sbo], SectorSize, sbo );
|
||||
actualSize -= SectorSize;
|
||||
sbo += SectorSize;
|
||||
@ -841,11 +692,11 @@ void MC_ManageSettings(int mode, int slot, int quiet) {
|
||||
|
||||
while ( CardError != CARD_ERROR_NOFILE ) {
|
||||
CardError = CARD_FindNext(&CardDir);
|
||||
if ( strcmp(CardDir.filename, mcFilename) == 0 )
|
||||
if (strcmp(CardDir.filename, mcFilename) == 0)
|
||||
found = 1;
|
||||
}
|
||||
|
||||
if ( found == 0 ) {
|
||||
if (found == 0) {
|
||||
strcpy(msg, "No Settings Found");
|
||||
if (quiet) ShowAction(msg);
|
||||
else WaitPrompt(msg);
|
||||
@ -884,125 +735,36 @@ void SD_ManageSettings(int mode, int slot, int quiet) {
|
||||
int len = 0;
|
||||
u8 buffer[128];
|
||||
|
||||
if (slot < 2) {
|
||||
sd_file *handle;
|
||||
sprintf (path, "dev%d:\\%s\\%s\\Settings.fcs", ChosenSlot, FCEUDIR, SAVEDIR);
|
||||
if (mode == 0) ShowAction ("Saving Settings to SD...");
|
||||
else ShowAction ("Loading Settings from SD...");
|
||||
|
||||
if (mode == 0) ShowAction ("Saving Settings to SD...");
|
||||
else ShowAction ("Loading Settings from SD...");
|
||||
sprintf(path, "/%s/%s/Settings.fcs", FCEUDIR, SAVEDIR);
|
||||
FILE *f = fopen(path, (mode == 0) ? "wb" : "rb");
|
||||
if (f == NULL) {
|
||||
sprintf(msg, "Couldn't open %s", path);
|
||||
if (quiet) ShowAction(msg);
|
||||
else WaitPrompt(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
handle = SDCARD_OpenFile(path, (mode == 0) ? "wb" : "rb");
|
||||
if (mode == 0) { // Save
|
||||
filesize = SaveSettings(buffer);
|
||||
len = fwrite(buffer, filesize, 1, f);
|
||||
fclose(f);
|
||||
|
||||
if (handle == NULL) {
|
||||
sprintf(msg, "Couldn't open %s", path);
|
||||
if (quiet) ShowAction(msg);
|
||||
else WaitPrompt(msg);
|
||||
return;
|
||||
}
|
||||
sprintf(msg, "Saved settings successfully");
|
||||
if (quiet) ShowAction(msg);
|
||||
else WaitPrompt(msg);
|
||||
} else { // Load
|
||||
fread(buffer, 128, 1, f);
|
||||
fclose(f);
|
||||
|
||||
if (mode == 0) { // Save
|
||||
filesize = SaveSettings(buffer);
|
||||
/*** Finally, do load ***/
|
||||
filesize = LoadSettings(buffer);
|
||||
|
||||
len = SDCARD_WriteFile(handle, buffer, filesize);
|
||||
SDCARD_CloseFile(handle);
|
||||
|
||||
if (len != filesize) {
|
||||
sprintf (msg, "Error writing %s", path);
|
||||
if (quiet) ShowAction(msg);
|
||||
else WaitPrompt(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
sprintf(msg, "Saved settings successfully");
|
||||
if (quiet) ShowAction(msg);
|
||||
else WaitPrompt(msg);
|
||||
} else { // Load
|
||||
len = SDCARD_ReadFile(handle, buffer, 128);
|
||||
SDCARD_CloseFile (handle);
|
||||
|
||||
/*** Finally, do load ***/
|
||||
filesize = LoadSettings(buffer);
|
||||
|
||||
sprintf (msg, "Loaded settings successfully");
|
||||
ShowAction(msg);
|
||||
return;
|
||||
}
|
||||
} else { // WiiSD
|
||||
#ifdef HW_RVL
|
||||
if (mode == 0) ShowAction ("Saving Settings to WiiSD...");
|
||||
else ShowAction ("Loading Settings from WiiSD...");
|
||||
|
||||
sprintf(path, "/%s/%s/Settings.fcs", FCEUDIR, SAVEDIR);
|
||||
FIL fp;
|
||||
int res;
|
||||
|
||||
/* Mount WiiSD with TinyFatFS*/
|
||||
if(f_mount(0, &frontfs) != FR_OK) {
|
||||
strcpy(msg, "f_mount failed");
|
||||
if (quiet) ShowAction(msg);
|
||||
else WaitPrompt(msg);
|
||||
return 0;
|
||||
}
|
||||
if (mode == 0)
|
||||
res = f_open(&fp, path, FA_CREATE_ALWAYS | FA_WRITE);
|
||||
else {
|
||||
if ((res=f_stat(path, &finfo)) != FR_OK) {
|
||||
if (res == FR_NO_FILE) {
|
||||
sprintf(msg, "Unable to find %s.", path);
|
||||
}
|
||||
else {
|
||||
sprintf(msg, "f_stat failed, error %d", res);
|
||||
}
|
||||
if (quiet) ShowAction(msg);
|
||||
else WaitPrompt(msg);
|
||||
return;
|
||||
}
|
||||
res = f_open(&fp, path, FA_READ);
|
||||
}
|
||||
|
||||
if (res != FR_OK) {
|
||||
sprintf(msg, "Failed to open %s, error %d.", path, res);
|
||||
if (quiet) ShowAction(msg);
|
||||
else WaitPrompt(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == 0) { // Save
|
||||
u32 written = 0;
|
||||
filesize = SaveSettings(buffer);
|
||||
|
||||
if ((res = f_write(&fp, buffer, filesize, &written)) != FR_OK) {
|
||||
sprintf(msg, "f_write failed, error %d", res);
|
||||
if (quiet) ShowAction(msg);
|
||||
else WaitPrompt(msg);
|
||||
f_close(&fp);
|
||||
return;
|
||||
}
|
||||
sprintf(msg, "Wrote %d bytes.", filesize);
|
||||
ShowAction(msg);
|
||||
f_close(&fp);
|
||||
return;
|
||||
} else { // Load
|
||||
u32 bytes_read = 0;
|
||||
filesize = 0;
|
||||
|
||||
if (f_read(&fp, &buffer, 128, &bytes_read) != FR_OK) {
|
||||
strcpy(msg, "f_read failed");
|
||||
if (quiet) ShowAction(msg);
|
||||
else WaitPrompt(msg);
|
||||
f_close(&fp);
|
||||
return;
|
||||
}
|
||||
|
||||
/*** Finally, do load ***/
|
||||
filesize = LoadSettings(buffer);
|
||||
|
||||
sprintf(msg, "Read %d bytes.", bytes_read);
|
||||
ShowAction(msg);
|
||||
f_close(&fp);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
sprintf (msg, "Loaded settings successfully");
|
||||
ShowAction(msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,8 @@
|
||||
* This file manages the 7zip support for this emulator.
|
||||
* Currently it only provides functions for loading a 7zip file from a DVD.
|
||||
****************************************************************************/
|
||||
#ifdef HW_DOL // only do 7zip in Gamecube mode for now...
|
||||
|
||||
#include "gcdvd.h"
|
||||
#include "sz.h"
|
||||
|
||||
extern u8 UseSDCARD;
|
||||
@ -225,7 +225,7 @@ SZ_RESULT SzDvdIsArchive(u64 dvd_offset) {
|
||||
Candidate[3],
|
||||
Candidate[4],
|
||||
Candidate[5]);
|
||||
//WaitPrompt(msg);
|
||||
WaitPrompt(msg);
|
||||
|
||||
size_t i;
|
||||
for(i = 0; i < 6; i++) {
|
||||
@ -364,3 +364,4 @@ bool SzExtractROM(int i, unsigned char *buffer)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1,137 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 svpe, #wiidev at efnet
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <gccore.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "sdio.h"
|
||||
#include "diskio.h"
|
||||
|
||||
DSTATUS disk_initialize (BYTE drv)
|
||||
{
|
||||
s32 r;
|
||||
if(drv != 0)
|
||||
return RES_PARERR;
|
||||
|
||||
r = sd_init();
|
||||
if(r == 0)
|
||||
return RES_OK;
|
||||
else
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
|
||||
DSTATUS disk_status ( BYTE drv )
|
||||
{
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
DRESULT disk_read (
|
||||
BYTE drv, /* Physical drive nmuber (0) */
|
||||
BYTE *buff, /* Data buffer to store read data */
|
||||
DWORD sector, /* Sector number (LBA) */
|
||||
BYTE count /* Sector count (1..255) */
|
||||
)
|
||||
{
|
||||
s32 r = -1;
|
||||
u32 i;
|
||||
|
||||
for(i = 0; i < count; i++)
|
||||
{
|
||||
r = sd_read(sector + i, buff + (0x200 * i));
|
||||
if(r < 0)
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
DRESULT disk_write (
|
||||
BYTE drv, /* Physical drive nmuber (0) */
|
||||
const BYTE *buff, /* Data buffer to store read data */
|
||||
DWORD sector, /* Sector number (LBA) */
|
||||
BYTE count /* Sector count (1..255) */
|
||||
)
|
||||
{
|
||||
s32 r = -1;
|
||||
u32 i;
|
||||
|
||||
for(i = 0; i < count; i++)
|
||||
{
|
||||
r = sd_write(sector + i, buff + (0x200 * i));
|
||||
if(r < 0)
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
DRESULT disk_ioctl (
|
||||
BYTE drv, /* Physical drive nmuber */
|
||||
BYTE ctrl, /* Control code */
|
||||
void *buff /* Buffer to send/receive data block */
|
||||
)
|
||||
{
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
u32 get_fattime( void )
|
||||
{
|
||||
int nday[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
|
||||
time_t now;
|
||||
int sec, min, hour, day, month, year;
|
||||
u32 ret;
|
||||
|
||||
time(&now);
|
||||
|
||||
sec = now % 60;
|
||||
now -= sec;
|
||||
now /= 60;
|
||||
|
||||
min = now % 60;
|
||||
now -= min;
|
||||
now /= 60;
|
||||
|
||||
hour = now % 24;
|
||||
now -= hour;
|
||||
|
||||
day = (int)now / 24;
|
||||
|
||||
for(year=1970; day>366; year++){
|
||||
if((year%4==0 && year%100!=0) || year%400==0)
|
||||
day -= 366;
|
||||
else
|
||||
day -= 365;
|
||||
}
|
||||
day++;
|
||||
|
||||
if((year%4==0 && year%100!=0) || year%400==0)
|
||||
nday[1]++;
|
||||
|
||||
for(month=0; month<12; month++){
|
||||
if(day <= nday[month])
|
||||
break;
|
||||
day -= nday[month];
|
||||
}
|
||||
month++;
|
||||
|
||||
ret = ((year-1980)<<25) | (month<<21) | (day<<16) | (hour<<11) |
|
||||
(min<<5) | (sec>>1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,63 +0,0 @@
|
||||
/*-----------------------------------------------------------------------
|
||||
/ Low level disk interface modlue include file R0.04a (C)ChaN, 2007
|
||||
/-----------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _DISKIO
|
||||
|
||||
#define _READONLY 0 /* 1: Read-only mode */
|
||||
|
||||
#include "integer.h"
|
||||
|
||||
|
||||
/* Status of Disk Functions */
|
||||
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 */
|
||||
} DRESULT;
|
||||
|
||||
|
||||
/*---------------------------------------*/
|
||||
/* Prototypes for disk control functions */
|
||||
|
||||
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*);
|
||||
void disk_timerproc (void);
|
||||
|
||||
|
||||
|
||||
|
||||
/* 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 */
|
||||
|
||||
|
||||
/* Command code for disk_ioctrl() */
|
||||
|
||||
#define GET_SECTOR_COUNT 1
|
||||
#define GET_SECTOR_SIZE 2
|
||||
#define CTRL_SYNC 3
|
||||
#define CTRL_POWER 4
|
||||
#define CTRL_LOCK 5
|
||||
#define CTRL_EJECT 6
|
||||
#define MMC_GET_CSD 10
|
||||
#define MMC_GET_CID 11
|
||||
#define MMC_GET_OCR 12
|
||||
#define ATA_GET_REV 20
|
||||
#define ATA_GET_MODEL 21
|
||||
#define ATA_GET_SN 22
|
||||
|
||||
#define _DISKIO
|
||||
#endif
|
@ -1,30 +0,0 @@
|
||||
/*-------------------------------------------*/
|
||||
/* Integer type definitions for FatFs module */
|
||||
/*-------------------------------------------*/
|
||||
|
||||
#ifndef _INTEGER
|
||||
|
||||
/* These types must be 16-bit, 32-bit or larger integer */
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
|
||||
/* These types must be 8-bit integer */
|
||||
typedef signed char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
/* These types must be 16-bit integer */
|
||||
typedef short SHORT;
|
||||
typedef unsigned short USHORT;
|
||||
typedef unsigned short WORD;
|
||||
|
||||
/* These types must be 32-bit integer */
|
||||
typedef long LONG;
|
||||
typedef unsigned long ULONG;
|
||||
typedef unsigned long DWORD;
|
||||
|
||||
/* Boolean type */
|
||||
//typedef enum { FALSE = 0, TRUE } BOOL;
|
||||
|
||||
#define _INTEGER
|
||||
#endif
|
@ -1,289 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 svpe, #wiidev at efnet
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
// pretty much everything here has been reversed from the twilight hack elf loader
|
||||
// my implementation is *really* bad and will fail fail in random situations.
|
||||
// it should not be used anywhere else. i recommend waiting for the libogc update.
|
||||
// you have been warned....
|
||||
|
||||
#include <gccore.h>
|
||||
#include <ogc/ipc.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static s32 sd_fd = -1;
|
||||
|
||||
static u32 status __attribute__((aligned(32)));
|
||||
|
||||
s32 sd_deinit();
|
||||
|
||||
s32 sd_send_cmd(u32 cmd, u32 type, u32 resp, u32 arg, u32 blocks, u32 bsize, u32 addr)
|
||||
{
|
||||
static u32 request[9] __attribute__((aligned(32)));
|
||||
static u32 reply[4] __attribute__((aligned(32)));
|
||||
u32 r;
|
||||
|
||||
memset(request, 0, sizeof(request));
|
||||
memset(reply, 0, sizeof(reply));
|
||||
|
||||
request[0] = cmd;
|
||||
request[1] = type;
|
||||
request[2] = resp;
|
||||
request[3] = arg;
|
||||
request[4] = blocks;
|
||||
request[5] = bsize;
|
||||
request[6] = addr;
|
||||
//request[7] = 0;
|
||||
//request[8] = 0;
|
||||
|
||||
r = IOS_Ioctl(sd_fd, 7, (u8 *)request, 36, (u8 *)reply, 0x10);
|
||||
//printf("sd_send_cmd(%x, %x, %x, %x, %x, %x, %x) = %d", cmd, type, resp, arg, blocks, bsize, addr, r);
|
||||
//printf(" -> %x %x %x %x\n", reply[0], reply[1], reply[2], reply[3]); // TODO: add some argument for this reply
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
s32 sd_reset()
|
||||
{
|
||||
s32 r;
|
||||
|
||||
r = IOS_Ioctl(sd_fd, 4, 0, 0, (u8 *)&status, 4);
|
||||
//printf("sd_reset(): r = %d; status = %d\n", r, status);
|
||||
return r;
|
||||
}
|
||||
|
||||
s32 sd_select()
|
||||
{
|
||||
s32 r;
|
||||
|
||||
r = sd_send_cmd(7, 3, 2, status & 0xFFFF0000, 0, 0, 0);
|
||||
//printf("sd_select(): r = %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
s32 sd_set_blocklen(u32 len)
|
||||
{
|
||||
s32 r;
|
||||
|
||||
r = sd_send_cmd(0x10, 3, 1, len, 0, 0, 0);
|
||||
//printf("sd_set_blocklen(%x) = %d\n", len, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
u8 sd_get_hcreg()
|
||||
{
|
||||
s32 r;
|
||||
static u32 data __attribute__((aligned(32)));
|
||||
static u32 query[6] __attribute__((aligned(32)));
|
||||
|
||||
memset(&data, 0, 4);
|
||||
memset(query, 0, 0x18);
|
||||
|
||||
query[0] = 0x28;
|
||||
query[3] = 1;
|
||||
//query[4] = 0;
|
||||
|
||||
r = IOS_Ioctl(sd_fd, 2, (u8 *)query, 0x18, (u8 *)&data, 4);
|
||||
//printf("sd_get_hcreg() = %d; r = %d\n", data & 0xFF, r);
|
||||
return data & 0xFF;
|
||||
}
|
||||
|
||||
s32 sd_set_hcreg(u8 value)
|
||||
{
|
||||
s32 r;
|
||||
static u32 query[6] __attribute__((aligned(32)));
|
||||
|
||||
memset(query, 0, 0x18);
|
||||
|
||||
query[0] = 0x28;
|
||||
query[3] = 1;
|
||||
query[4] = value;
|
||||
|
||||
r = IOS_Ioctl(sd_fd, 1, (u8 *)query, 0x18, 0, 0);
|
||||
//printf("sd_set_hcreg(%d) = %d\n", value, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
s32 sd_set_buswidth(u8 w)
|
||||
{
|
||||
s32 r;
|
||||
u8 reg;
|
||||
|
||||
r = sd_send_cmd(0x37, 3, 1, status & 0xFFFF0000, 0, 0, 0);
|
||||
if(r < 0)
|
||||
return r;
|
||||
r = sd_send_cmd(6, 3, 1, (w == 4 ? 2 : 0), 0, 0, 0);
|
||||
if(r < 0)
|
||||
return r;
|
||||
|
||||
reg = sd_get_hcreg();
|
||||
|
||||
reg &= ~2;
|
||||
if(w == 4)
|
||||
reg |= 2;
|
||||
return sd_set_hcreg(reg);
|
||||
}
|
||||
|
||||
s32 sd_clock()
|
||||
{
|
||||
s32 r;
|
||||
static u32 c __attribute__((aligned(32)));
|
||||
|
||||
c = 1;
|
||||
r = IOS_Ioctl(sd_fd, 6, &c, 4, 0, 0);
|
||||
//printf("sd_clock() = %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
s32 sd_read(u32 n, u8 *buf)
|
||||
{
|
||||
s32 r;
|
||||
static u8 buffer[0x200] __attribute__((aligned(32)));
|
||||
static u32 query[9] __attribute__((aligned(32)));
|
||||
static u32 res[4] __attribute__((aligned(32)));
|
||||
|
||||
static ioctlv v[3] __attribute__((aligned(32)));
|
||||
|
||||
// printf("sd_read(%d) called\n", n);
|
||||
|
||||
memset(buffer, 0xAA, 0x200); // why is this buffer filled with 0xAA? is this really needed?
|
||||
memset(query, 0, 0x24);
|
||||
memset(res, 0, 0x10);
|
||||
|
||||
query[0] = 0x12;
|
||||
query[1] = 3;
|
||||
query[2] = 1;
|
||||
query[3] = n * 0x200; // arg
|
||||
query[4] = 1; // block_count
|
||||
query[5] = 0x200; // sector size
|
||||
query[6] = (u32)buffer; // buffer
|
||||
query[7] = 1; // ?
|
||||
query[8] = 0; // ?
|
||||
|
||||
v[0].data = (u32 *)query;
|
||||
v[0].len = 0x24;
|
||||
v[1].data =(u32 *)buffer;
|
||||
v[1].len = 0x200;
|
||||
v[2].data = (u32 *)res;
|
||||
v[2].len = 0x10;
|
||||
|
||||
// FIXME: is this really needed? twilight hack loader does it.
|
||||
DCFlushRange(buffer, 0x200);
|
||||
DCInvalidateRange(buffer, 0x200);
|
||||
|
||||
r = IOS_Ioctlv(sd_fd, 7, 2, 1, v);
|
||||
|
||||
if(r != 0)
|
||||
{
|
||||
//printf("sd_read() = %d\n", r);
|
||||
//printf(" %x %x %x %x\n", res[0], res[1], res[2], res[3]);
|
||||
return r;
|
||||
}
|
||||
|
||||
memcpy(buf, buffer, 0x200);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 sd_write(u32 n, const u8 *buf)
|
||||
{
|
||||
s32 r;
|
||||
static u8 buffer[0x200] __attribute__((aligned(32)));
|
||||
static u32 query[9] __attribute__((aligned(32)));
|
||||
static u32 res[4] __attribute__((aligned(32)));
|
||||
|
||||
static ioctlv v[3] __attribute__((aligned(32)));
|
||||
|
||||
// printf("sd_write(%d) called\n", n);
|
||||
|
||||
memcpy(buffer, buf, 0x200);
|
||||
memset(query, 0, 0x24);
|
||||
memset(res, 0, 0x10);
|
||||
|
||||
query[0] = 0x19;
|
||||
query[1] = 3;
|
||||
query[2] = 1;
|
||||
query[3] = n * 0x200; // arg
|
||||
query[4] = 1; // block_count
|
||||
query[5] = 0x200; // sector size
|
||||
query[6] = (u32)buffer; // buffer
|
||||
query[7] = 1; // ?
|
||||
query[8] = 0; // ?
|
||||
|
||||
v[0].data = (u32 *)query;
|
||||
v[0].len = 0x24;
|
||||
v[1].data =(u32 *)buffer;
|
||||
v[1].len = 0x200;
|
||||
v[2].data = (u32 *)res;
|
||||
v[2].len = 0x10;
|
||||
|
||||
r = IOS_Ioctlv(sd_fd, 7, 2, 1, v);
|
||||
|
||||
if(r != 0)
|
||||
{
|
||||
//printf("sd_write() = %d\n", r);
|
||||
//printf(" %x %x %x %x\n", res[0], res[1], res[2], res[3]);
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 sd_init()
|
||||
{
|
||||
s32 r;
|
||||
|
||||
if(sd_fd > 0)
|
||||
{
|
||||
//printf("sd_init() called more than once. using old sd_fd: %d\n", sd_fd);
|
||||
//return 0;
|
||||
sd_deinit();
|
||||
}
|
||||
|
||||
sd_fd = IOS_Open("/dev/sdio/slot0", 0);
|
||||
//printf("sd_fd = %d\n", sd_fd);
|
||||
if(sd_fd < 0)
|
||||
return sd_fd;
|
||||
|
||||
|
||||
// TODO: close sd_fd on failure and do proper error check here
|
||||
r = sd_reset();
|
||||
if(r < 0)
|
||||
return r;
|
||||
|
||||
sd_select();
|
||||
r = sd_set_blocklen(0x200);
|
||||
if(r < 0)
|
||||
return sd_fd;
|
||||
r = sd_set_buswidth(4);
|
||||
if(r < 0)
|
||||
return sd_fd;
|
||||
r = sd_clock();
|
||||
if(r < 0)
|
||||
return sd_fd;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
s32 sd_deinit()
|
||||
{
|
||||
sd_reset();
|
||||
return IOS_Close(sd_fd);
|
||||
}
|
||||
|
||||
|
@ -1,5 +0,0 @@
|
||||
extern s32 sd_read(u32 n, u8 *buf);
|
||||
extern s32 sd_write(u32 n, const u8 *buf);
|
||||
extern s32 sd_init();
|
||||
extern s32 sd_deinit();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,306 +0,0 @@
|
||||
/*--------------------------------------------------------------------------/
|
||||
/ Tiny-FatFs - FAT file system module include file R0.06 (C)ChaN, 2008
|
||||
/---------------------------------------------------------------------------/
|
||||
/ FatFs module is an experimenal project to implement FAT file system to
|
||||
/ cheap microcontrollers. This is a free software and is opened for education,
|
||||
/ research and development under license policy of following trems.
|
||||
/
|
||||
/ Copyright (C) 2008, ChaN, all right reserved.
|
||||
/
|
||||
/ * The FatFs module is a free software and there is no warranty.
|
||||
/ * You can use, modify and/or redistribute it for personal, non-profit or
|
||||
/ commercial use without any restriction under your responsibility.
|
||||
/ * Redistributions of source code must retain the above copyright notice.
|
||||
/
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _FATFS
|
||||
|
||||
#define _MCU_ENDIAN 2
|
||||
/* The _MCU_ENDIAN defines which access method is used to the FAT structure.
|
||||
/ 1: Enable word access.
|
||||
/ 2: Disable word access and use byte-by-byte access instead.
|
||||
/ When the architectural byte order of the MCU is big-endian and/or address
|
||||
/ miss-aligned access results incorrect behavior, the _MCU_ENDIAN must be set to 2.
|
||||
/ If it is not the case, it can also be set to 1 for good code efficiency. */
|
||||
|
||||
#define _FS_READONLY 0
|
||||
/* 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, f_getfree and internal writing codes. */
|
||||
|
||||
#define _FS_MINIMIZE 0
|
||||
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
|
||||
/ 0: Full function.
|
||||
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename are removed.
|
||||
/ 2: f_opendir and f_readdir are removed in addition to level 1.
|
||||
/ 3: f_lseek is removed in addition to level 2. */
|
||||
|
||||
#define _USE_STRFUNC 0
|
||||
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
|
||||
|
||||
#define _USE_FORWARD 0
|
||||
/* To enable f_forward function, set _USE_FORWARD to 1. */
|
||||
|
||||
#define _FAT32 1
|
||||
/* To enable FAT32 support in addition of FAT12/16, set _FAT32 to 1. */
|
||||
|
||||
#define _USE_FSINFO 0
|
||||
/* To enable FSInfo support on FAT32 volume, set _USE_FSINFO to 1. */
|
||||
|
||||
#define _USE_SJIS 0
|
||||
/* When _USE_SJIS is set to 1, Shift-JIS code transparency is enabled, otherwise
|
||||
/ only US-ASCII(7bit) code can be accepted as file/directory name. */
|
||||
|
||||
#define _USE_NTFLAG 0
|
||||
/* When _USE_NTFLAG is set to 1, upper/lower case of the file name is preserved.
|
||||
/ Note that the files are always accessed in case insensitive. */
|
||||
|
||||
|
||||
#include "integer.h"
|
||||
|
||||
|
||||
/* Type definition for cluster number */
|
||||
#if _FAT32
|
||||
typedef DWORD CLUST;
|
||||
#else
|
||||
typedef WORD CLUST;
|
||||
#undef _USE_FSINFO
|
||||
#define _USE_FSINFO 0
|
||||
#endif
|
||||
|
||||
|
||||
/* File system object structure */
|
||||
typedef struct _FATFS {
|
||||
WORD id; /* File system mount ID */
|
||||
WORD n_rootdir; /* Number of root directory entries */
|
||||
DWORD winsect; /* Current sector appearing in the win[] */
|
||||
DWORD fatbase; /* FAT start sector */
|
||||
DWORD dirbase; /* Root directory start sector */
|
||||
DWORD database; /* Data start sector */
|
||||
CLUST sects_fat; /* Sectors per fat */
|
||||
CLUST max_clust; /* Maximum cluster# + 1 */
|
||||
#if !_FS_READONLY
|
||||
CLUST last_clust; /* Last allocated cluster */
|
||||
CLUST free_clust; /* Number of free clusters */
|
||||
#if _USE_FSINFO
|
||||
DWORD fsi_sector; /* fsinfo sector */
|
||||
BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */
|
||||
BYTE pad1;
|
||||
#endif
|
||||
#endif
|
||||
BYTE fs_type; /* FAT sub type */
|
||||
BYTE csize; /* Number of sectors per cluster */
|
||||
BYTE n_fats; /* Number of FAT copies */
|
||||
BYTE winflag; /* win[] dirty flag (1:must be written back) */
|
||||
BYTE win[512]; /* Disk access window for Directory/FAT/File */
|
||||
} FATFS;
|
||||
|
||||
|
||||
/* Directory object structure */
|
||||
typedef struct _DIRECTORY {
|
||||
WORD id; /* Owner file system mount ID */
|
||||
WORD index; /* Current index */
|
||||
FATFS* fs; /* Pointer to the owner file system object */
|
||||
CLUST sclust; /* Start cluster */
|
||||
CLUST clust; /* Current cluster */
|
||||
DWORD sect; /* Current sector */
|
||||
} DIRECTORY;
|
||||
|
||||
|
||||
/* File object structure */
|
||||
typedef struct _FIL {
|
||||
WORD id; /* Owner file system mount ID */
|
||||
BYTE flag; /* File status flags */
|
||||
BYTE csect; /* Sector address in the cluster */
|
||||
FATFS* fs; /* Pointer to owner file system */
|
||||
DWORD fptr; /* File R/W pointer */
|
||||
DWORD fsize; /* File size */
|
||||
CLUST org_clust; /* File start cluster */
|
||||
CLUST curr_clust; /* Current cluster */
|
||||
DWORD curr_sect; /* Current sector */
|
||||
#if !_FS_READONLY
|
||||
DWORD dir_sect; /* Sector containing the directory entry */
|
||||
BYTE* dir_ptr; /* Ponter to the directory entry in the window */
|
||||
#endif
|
||||
} FIL;
|
||||
|
||||
|
||||
/* File status structure */
|
||||
typedef struct _FILINFO {
|
||||
DWORD fsize; /* Size */
|
||||
WORD fdate; /* Date */
|
||||
WORD ftime; /* Time */
|
||||
BYTE fattrib; /* Attribute */
|
||||
char fname[8+1+3+1]; /* Name (8.3 format) */
|
||||
} FILINFO;
|
||||
|
||||
|
||||
/* File function return code (FRESULT) */
|
||||
|
||||
typedef enum {
|
||||
FR_OK = 0, /* 0 */
|
||||
FR_NOT_READY, /* 1 */
|
||||
FR_NO_FILE, /* 2 */
|
||||
FR_NO_PATH, /* 3 */
|
||||
FR_INVALID_NAME, /* 4 */
|
||||
FR_INVALID_DRIVE, /* 5 */
|
||||
FR_DENIED, /* 6 */
|
||||
FR_EXIST, /* 7 */
|
||||
FR_RW_ERROR, /* 8 */
|
||||
FR_WRITE_PROTECTED, /* 9 */
|
||||
FR_NOT_ENABLED, /* 10 */
|
||||
FR_NO_FILESYSTEM, /* 11 */
|
||||
FR_INVALID_OBJECT, /* 12 */
|
||||
FR_MKFS_ABORTED /* 13 (not used) */
|
||||
} FRESULT;
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------*/
|
||||
/* Tiny-FatFs module application interface */
|
||||
|
||||
FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */
|
||||
FRESULT f_open (FIL*, const char*, BYTE); /* Open or create a file */
|
||||
FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */
|
||||
FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to 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 (DIRECTORY*, const char*); /* Open an existing directory */
|
||||
FRESULT f_readdir (DIRECTORY*, FILINFO*); /* Read a directory item */
|
||||
FRESULT f_stat (const char*, FILINFO*); /* Get file status */
|
||||
FRESULT f_getfree (const char*, 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 char*); /* Delete an existing file or directory */
|
||||
FRESULT f_mkdir (const char*); /* Create a new directory */
|
||||
FRESULT f_chmod (const char*, BYTE, BYTE); /* Change file/dir attriburte */
|
||||
FRESULT f_utime (const char*, const FILINFO*); /* Change file/dir timestamp */
|
||||
FRESULT f_rename (const char*, const char*); /* Rename/Move a file or directory */
|
||||
FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */
|
||||
#if _USE_STRFUNC
|
||||
#define feof(fp) ((fp)->fptr == (fp)->fsize)
|
||||
#define EOF -1
|
||||
int fputc (int, FIL*); /* Put a character to the file */
|
||||
int fputs (const char*, FIL*); /* Put a string to the file */
|
||||
int fprintf (FIL*, const char*, ...); /* Put a formatted string to the file */
|
||||
char* fgets (char*, int, FIL*); /* Get a string from the file */
|
||||
#endif
|
||||
|
||||
|
||||
/* User defined function to give a current time to fatfs module */
|
||||
|
||||
DWORD get_fattime (void); /* 31-25: Year(0-127 +1980), 24-21: Month(1-12), 20-16: Day(1-31) */
|
||||
/* 15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */
|
||||
|
||||
|
||||
|
||||
/* File access control and file status flags (FIL.flag) */
|
||||
|
||||
#define FA_READ 0x01
|
||||
#define FA_OPEN_EXISTING 0x00
|
||||
#if !_FS_READONLY
|
||||
#define FA_WRITE 0x02
|
||||
#define FA_CREATE_NEW 0x04
|
||||
#define FA_CREATE_ALWAYS 0x08
|
||||
#define FA_OPEN_ALWAYS 0x10
|
||||
#define FA__WRITTEN 0x20
|
||||
#endif
|
||||
#define FA__ERROR 0x80
|
||||
|
||||
|
||||
/* FAT sub type (FATFS.fs_type) */
|
||||
|
||||
#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 */
|
||||
|
||||
|
||||
|
||||
/* Offset of FAT structure members */
|
||||
|
||||
#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_55AA 510
|
||||
|
||||
#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 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
|
||||
|
||||
|
||||
|
||||
/* Multi-byte word access macros */
|
||||
|
||||
#if _MCU_ENDIAN == 1 /* Use word access */
|
||||
#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)
|
||||
#elif _MCU_ENDIAN == 2 /* Use byte-by-byte access */
|
||||
#define LD_WORD(ptr) (WORD)(((WORD)*(volatile BYTE*)((ptr)+1)<<8)|(WORD)*(volatile BYTE*)(ptr))
|
||||
#define LD_DWORD(ptr) (DWORD)(((DWORD)*(volatile BYTE*)((ptr)+3)<<24)|((DWORD)*(volatile BYTE*)((ptr)+2)<<16)|((WORD)*(volatile BYTE*)((ptr)+1)<<8)|*(volatile BYTE*)(ptr))
|
||||
#define ST_WORD(ptr,val) *(volatile BYTE*)(ptr)=(BYTE)(val); *(volatile BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8)
|
||||
#define ST_DWORD(ptr,val) *(volatile BYTE*)(ptr)=(BYTE)(val); *(volatile BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(volatile BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(volatile BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24)
|
||||
#else
|
||||
#error Do not forget to set _MCU_ENDIAN properly!
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define _FATFS
|
||||
#endif /* _FATFS */
|
@ -1,93 +0,0 @@
|
||||
/****************************************************************************
|
||||
* FAT16 - VFAT Support
|
||||
*
|
||||
* NOTE: Only supports FAT16 with Long File Names
|
||||
* I have no interest in adding FAT32
|
||||
*
|
||||
* Reference Documentation:
|
||||
*
|
||||
* FAT: General Overview of On-Disk Format
|
||||
* Version 1.02 May 05, 1999
|
||||
* Microsoft Corporation
|
||||
*
|
||||
* FAT: General Overview of On-Disk Format
|
||||
* Version 1.03 December 06, 2000
|
||||
* Microsoft Corporation
|
||||
*
|
||||
* This is targetted at MMC/SD cards.
|
||||
*
|
||||
* Copyright softdev 2007. All rights reserved.
|
||||
*
|
||||
* Diskio Module
|
||||
* -------------
|
||||
*
|
||||
* This module is almost identical to the one found in ChaN's TinyFAT FS.
|
||||
* It's a logical abstration after all :)
|
||||
*
|
||||
* This covers stdio file on a SD image file
|
||||
*
|
||||
* 03/08: quickly modified by eke-eke to support Wii Front SD
|
||||
****************************************************************************/
|
||||
#include <gccore.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sdio.h"
|
||||
#include "vfat.h"
|
||||
|
||||
#define CARDIO_ERROR_READY 0
|
||||
|
||||
|
||||
/* End of not so public exports */
|
||||
|
||||
/****************************************************************************
|
||||
* DISKIO_Init
|
||||
*
|
||||
* Initialise communication with the disc
|
||||
****************************************************************************/
|
||||
int DISKIO_Init( int drive )
|
||||
{
|
||||
int res;
|
||||
|
||||
if ( drive < 0 || drive > 1 )
|
||||
return FS_ERR_PARAM;
|
||||
|
||||
res = sd_init();
|
||||
|
||||
if ( res == CARDIO_ERROR_READY )
|
||||
return FS_SUCCESS;
|
||||
|
||||
return FS_ERR_IO;
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DISKIO_ReadSectors
|
||||
*
|
||||
* Read sectors from the disc
|
||||
****************************************************************************/
|
||||
int DISKIO_ReadSectors( int drive, void *buffer, int sector, int count )
|
||||
{
|
||||
int res = -1;
|
||||
int i;
|
||||
int bytes = 0;
|
||||
|
||||
if ( drive != 0 && drive != 1 )
|
||||
return FS_ERR_PARAM; /* Must be 0 or 1 */
|
||||
|
||||
/* libOGC appears to only read in single sectors */
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
res = sd_read(sector + i, buffer + bytes);
|
||||
if ( res != CARDIO_ERROR_READY )
|
||||
return FS_ERR_IO;
|
||||
bytes += SECTOR_SIZE;
|
||||
}
|
||||
|
||||
if ( res == CARDIO_ERROR_READY )
|
||||
return FS_SUCCESS;
|
||||
|
||||
return FS_ERR_IO;
|
||||
|
||||
}
|
||||
|
@ -1,36 +0,0 @@
|
||||
/****************************************************************************
|
||||
* FAT16 - VFAT Support
|
||||
*
|
||||
* NOTE: Only supports FAT16 with Long File Names
|
||||
* I have no interest in adding FAT32
|
||||
*
|
||||
* Reference Documentation:
|
||||
*
|
||||
* FAT: General Overview of On-Disk Format
|
||||
* Version 1.02 May 05, 1999
|
||||
* Microsoft Corporation
|
||||
*
|
||||
* FAT: General Overview of On-Disk Format
|
||||
* Version 1.03 December 06, 2000
|
||||
* Microsoft Corporation
|
||||
*
|
||||
* This is targetted at MMC/SD cards.
|
||||
*
|
||||
* Copyright softdev 2007. All rights reserved.
|
||||
*
|
||||
* Diskio Module
|
||||
* -------------
|
||||
*
|
||||
* This module is almost identical to the one found in ChaN's TinyFAT FS.
|
||||
* It's a logical abstration after all :)
|
||||
*
|
||||
* This covers stdio file on a SD image file
|
||||
****************************************************************************/
|
||||
#ifndef __DISKIO__
|
||||
#define __DISKIO__
|
||||
|
||||
int DISKIO_Init( int drive );
|
||||
int DISKIO_ReadSectors( int drive, void *buffer, int sector, int count );
|
||||
|
||||
#endif
|
||||
|
@ -1,924 +0,0 @@
|
||||
/****************************************************************************
|
||||
* FAT16 - VFAT Support
|
||||
*
|
||||
* NOTE: Only supports FAT16 with Long File Names
|
||||
* I have no interest in adding FAT32
|
||||
*
|
||||
* Reference Documentation:
|
||||
*
|
||||
* FAT: General Overview of On-Disk Format
|
||||
* Version 1.02 May 05, 1999
|
||||
* Microsoft Corporation
|
||||
*
|
||||
* FAT: General Overview of On-Disk Format
|
||||
* Version 1.03 December 06, 2000
|
||||
* Microsoft Corporation
|
||||
*
|
||||
* This is targetted at MMC/SD cards.
|
||||
*
|
||||
* Copyright softdev 2007. All rights reserved.
|
||||
*
|
||||
* $Date: 2007-08-05 14:27:48 +0100 (Sun, 05 Aug 2007) $
|
||||
* $Rev: 8 $
|
||||
****************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "vfat.h"
|
||||
#include "vdiskio.h"
|
||||
|
||||
static BYTE sector[SECTOR_SIZE]; /**< Local sector buffer */
|
||||
static VFATFS *vfs[2]; /**< VFATFS Pointers for 2 drives */
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define strcasecmp stricmp
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Z E R O S E C T O R / B I O S P A R A M E T E R B L O C K
|
||||
*
|
||||
* These functions take care of parsing the 0th sector/BPB
|
||||
* Supports SuperFloppy Format and standard partitioning.
|
||||
*
|
||||
*/
|
||||
|
||||
/**\defgroup INTERNALS VFATFS Private Functions
|
||||
* \brief These are internal helper functions and should
|
||||
* not be called by an application!\n
|
||||
* They are documented here for convenience only.
|
||||
*/
|
||||
|
||||
/**\ingroup INTERNALS
|
||||
* \brief Check for BIOS Parameter Block
|
||||
* \param sector 512 byte sector data
|
||||
* \return FS_TYPE_FAT16 on success
|
||||
*/
|
||||
static int BPBCheck( BYTE *sector )
|
||||
{
|
||||
BPB16 *bpb = (BPB16 *)sector;
|
||||
|
||||
/* Check signatures */
|
||||
if ( ( bpb->sigkey1 == 0x55 ) && ( bpb->sigkey2 == 0xAA ) )
|
||||
{
|
||||
/* Check for FAT16 signature */
|
||||
if ( memcmp(bpb->FilSysType, "FAT16", 5) == 0 )
|
||||
return FS_TYPE_FAT16;
|
||||
/* Non MS utilities simply put FAT */
|
||||
if ( memcmp(bpb->FilSysType, "FAT", 3) == 0 )
|
||||
return FS_TYPE_FAT16;
|
||||
}
|
||||
|
||||
return FS_TYPE_NONE;
|
||||
}
|
||||
|
||||
/** \ingroup INTERNALS
|
||||
* \brief Partition Entry Check
|
||||
* \param sector 512 byte sector data
|
||||
* \return Partition Start LBA on success
|
||||
*/
|
||||
static unsigned int PECheck( BYTE *sector )
|
||||
{
|
||||
int i;
|
||||
PARTENTRY *pe;
|
||||
|
||||
if ( ( sector[SECTOR_SIZE-2] == 0x55 ) && ( sector[SECTOR_SIZE-1] == 0xAA ) )
|
||||
{
|
||||
/* Find a FAT16 partition entry */
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
pe = (PARTENTRY *)(sector + 446 + (i<<4));
|
||||
if ( pe->partitiontype == 0x06 )
|
||||
{
|
||||
return SWAP32(pe->partitionstart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FS_TYPE_NONE;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* VFAT_Mount
|
||||
*
|
||||
* Function to mount a FAT16-VFAT volume
|
||||
***************************************************************************/
|
||||
int VFAT_mount( int driveid, VFATFS *v )
|
||||
{
|
||||
int ret;
|
||||
unsigned int bpbsector = 0;
|
||||
BPB16 *bpb = (BPB16 *)sector;
|
||||
BYTE media = 0;
|
||||
|
||||
if ( driveid < 0 || driveid > 1 )
|
||||
return FS_TYPE_NONE;
|
||||
|
||||
memset(v, 0, sizeof(VFATFS));
|
||||
|
||||
/* Copy pointer */
|
||||
vfs[driveid] = v;
|
||||
|
||||
if ( DISKIO_Init( driveid ) != FS_SUCCESS )
|
||||
return FS_ERR_IO;
|
||||
|
||||
if ( DISKIO_ReadSectors( driveid, sector, 0, 1 ) != FS_SUCCESS )
|
||||
return FS_ERR_IO;
|
||||
|
||||
/* Check for SuperFloppy Format */
|
||||
ret = BPBCheck( sector );
|
||||
|
||||
if ( ret == FS_TYPE_NONE )
|
||||
{
|
||||
/* Check for Partition Entry */
|
||||
bpbsector = PECheck(sector);
|
||||
if ( !bpbsector )
|
||||
return FS_TYPE_NONE;
|
||||
|
||||
if ( DISKIO_ReadSectors( driveid, sector, bpbsector, 1 ) != FS_SUCCESS )
|
||||
return FS_ERR_IO;
|
||||
|
||||
/* Check BPB */
|
||||
ret = BPBCheck( sector );
|
||||
}
|
||||
|
||||
if ( ret == FS_TYPE_FAT16 )
|
||||
{
|
||||
/* Capture defaults to machine native format */
|
||||
v->BaseOffset = bpbsector;
|
||||
v->BytesPerSector = SWAP16(bpb->bytesPerSec);
|
||||
v->SectorsPerFAT = SWAP16(bpb->FATsz16);
|
||||
v->ReservedSectors = SWAP16(bpb->reservedSec);
|
||||
v->NumberOfFATs = bpb->numFATs;
|
||||
v->SectorsPerCluster = bpb->secPerClust;
|
||||
v->RootDirEntries = SWAP16(bpb->rootEntCount);
|
||||
|
||||
/* Calculate number of root directory sectors */
|
||||
v->RootDirSectors = ( ( SWAP16(bpb->rootEntCount) << 5 ) + ( v->BytesPerSector - 1 ) ) / v->BytesPerSector;
|
||||
|
||||
/* First data sector */
|
||||
v->FirstDataSector = v->ReservedSectors + (v->NumberOfFATs * v->SectorsPerFAT) + v->RootDirSectors + v->BaseOffset;
|
||||
|
||||
/* Total sectors */
|
||||
if ( bpb->totSec16 == 0 )
|
||||
v->TotalSectors = SWAP32(bpb->totSec32);
|
||||
else
|
||||
v->TotalSectors = SWAP16(bpb->totSec16);
|
||||
|
||||
/* Data Sectors */
|
||||
v->DataSectors = v->TotalSectors - ( v->ReservedSectors + ( v->NumberOfFATs * v->SectorsPerFAT ) + v->RootDirSectors );
|
||||
|
||||
/* Count of clusters */
|
||||
v->CountOfClusters = v->DataSectors / bpb->secPerClust;
|
||||
|
||||
/* From v1.03 Document - Page 14 - FAT Type Determination */
|
||||
if ( v->CountOfClusters < 4085 )
|
||||
return FS_TYPE_NONE; /* FAT12 Volume */
|
||||
else
|
||||
{
|
||||
if ( v->CountOfClusters >= 65525 )
|
||||
return FS_TYPE_NONE; /* FAT32 Volume */
|
||||
}
|
||||
|
||||
/* Root Directory Offset */
|
||||
v->RootDirOffset = v->ReservedSectors + ( bpb->numFATs * v->SectorsPerFAT ) + v->BaseOffset;
|
||||
|
||||
/* First copy of FAT offset */
|
||||
v->FirstFATOffset = v->ReservedSectors + v->BaseOffset;
|
||||
|
||||
media = bpb->media;
|
||||
|
||||
/* Read first FAT */
|
||||
if ( DISKIO_ReadSectors( driveid, sector, v->FirstFATOffset, 1 ) != FS_SUCCESS )
|
||||
return FS_ERR_IO;
|
||||
|
||||
if ( sector[0] == media )
|
||||
{
|
||||
/* Allocate work spaces */
|
||||
v->FAT = (WORD *)malloc(v->SectorsPerFAT * SECTOR_SIZE);
|
||||
if ( v->FAT == NULL )
|
||||
return FS_ERR_NOMEM;
|
||||
|
||||
/* Save time running in and out - just load up the FAT table */
|
||||
if ( DISKIO_ReadSectors(driveid, v->FAT, v->FirstFATOffset, v->SectorsPerFAT) != FS_SUCCESS )
|
||||
{
|
||||
free(v->FAT);
|
||||
return FS_ERR_IO;
|
||||
}
|
||||
|
||||
/* Likewise, the same for the root directory */
|
||||
v->rootDir = (BYTE *)malloc(v->BytesPerSector * v->RootDirSectors);
|
||||
if ( v->rootDir == NULL )
|
||||
{
|
||||
free(v->FAT);
|
||||
return FS_ERR_NOMEM;
|
||||
}
|
||||
|
||||
/* Read root directory */
|
||||
if ( DISKIO_ReadSectors(driveid, v->rootDir, v->RootDirOffset, v->RootDirSectors) != FS_SUCCESS )
|
||||
{
|
||||
free(v->FAT);
|
||||
free(v->rootDir);
|
||||
return FS_ERR_IO;
|
||||
}
|
||||
return FS_TYPE_FAT16;
|
||||
}
|
||||
}
|
||||
|
||||
return FS_TYPE_NONE;
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* VFAT_unmount
|
||||
*
|
||||
* Release memory allocated by from a mounted VFATFS
|
||||
****************************************************************************/
|
||||
void VFAT_unmount( int driveid, VFATFS *v )
|
||||
{
|
||||
if ( v->FAT != NULL )
|
||||
free(v->FAT);
|
||||
|
||||
if ( v->rootDir != NULL )
|
||||
free(v->rootDir);
|
||||
|
||||
vfs[driveid] = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* F I L E N A M I N G S U P P O R T
|
||||
*
|
||||
* Routines to en/decode long and short file names
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* CalcShortNameChecksum
|
||||
*
|
||||
* Calculate the checksum for a short filename
|
||||
* Filename should be in UPPER case, and padded with spaces to match
|
||||
* a standard directory entry
|
||||
****************************************************************************/
|
||||
/** \ingroup INTERNALS
|
||||
* \brief Calculate the checksum of a short directory name
|
||||
* \param fname 11 character, space padded short directory name
|
||||
* \return checksum
|
||||
*/
|
||||
static unsigned char CalcShortNameCheckSum( BYTE *fname )
|
||||
{
|
||||
int i;
|
||||
unsigned char sum = 0;
|
||||
|
||||
for( i = 0; i < 11; i++ )
|
||||
sum = ( ( sum & 1 ) ? 0x80 : 0 ) + ( sum >> 1 ) + fname[i];
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* BuildShortNameFromDirEntry
|
||||
*
|
||||
* User friendly shortname
|
||||
****************************************************************************/
|
||||
/** \ingroup INTERNALS
|
||||
* \brief Convert a short directory entry to an application friendly name
|
||||
* \param sfn SFNDIRREC pointer
|
||||
* \param out Buffer to hold converted file name
|
||||
* \return None
|
||||
*/
|
||||
static void BuildShortNameFromDirEntry( SFNDIRREC *sfn, BYTE *out )
|
||||
{
|
||||
int i,j;
|
||||
|
||||
for(i = 0, j = 0; i < 11; i++ )
|
||||
{
|
||||
if ( sfn->dirname[i] != 32 )
|
||||
{
|
||||
out[j++] = sfn->dirname[i];
|
||||
}
|
||||
|
||||
if ( (i == 7) && ( sfn->dirname[8] != 32 ) )
|
||||
out[j++] = '.';
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* BuildLongNameFromDirEntry
|
||||
*
|
||||
* Build a long name from unicode to asciiz.
|
||||
* Each directory entry may contain up to 13 characters for sub entry.
|
||||
****************************************************************************/
|
||||
/** \ingroup INTERNALS
|
||||
* \brief Build a long file name as ASCIIZ
|
||||
* \param lfn LFNDIRREC pointer
|
||||
* \param position LFN directory record number
|
||||
* \param out Output buffer
|
||||
* \return None.
|
||||
*/
|
||||
static void BuildLongNameFromDirEntry( LFNDIRREC *lfn, int position, BYTE *out )
|
||||
{
|
||||
int j = ( ( position - 1 ) * 13 );
|
||||
int i;
|
||||
|
||||
/* Part one */
|
||||
for( i = 0; i < 10; i += 2 )
|
||||
{
|
||||
if ( lfn->dirname1[i] == 0xFF )
|
||||
return;
|
||||
|
||||
out[j++] = lfn->dirname1[i];
|
||||
}
|
||||
|
||||
/* Part two */
|
||||
for( i = 0; i < 12; i += 2 )
|
||||
{
|
||||
if ( lfn->dirname2[i] == 0xFF )
|
||||
return;
|
||||
|
||||
out[j++] = lfn->dirname2[i];
|
||||
}
|
||||
|
||||
/* Part three */
|
||||
for( i = 0; i < 4; i += 2 )
|
||||
{
|
||||
if ( lfn->dirname3[i] == 0xFF )
|
||||
return;
|
||||
|
||||
out[j++] = lfn->dirname3[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* D I R E C T O R Y F U N C T I O N S
|
||||
*
|
||||
* These routines take care of all directory level parsing
|
||||
*/
|
||||
|
||||
/** \ingroup INTERNALS
|
||||
* \brief Retrieve first sector number of a cluster
|
||||
* \param drive Device drive number
|
||||
* \param cluster Cluster number to determine first sector of
|
||||
* \return First sector of cluster
|
||||
*/
|
||||
static int SectorFromCluster( int drive, int cluster )
|
||||
{
|
||||
VFATFS *v = vfs[drive];
|
||||
return ( ( cluster - 2 ) * v->SectorsPerCluster ) + v->FirstDataSector;
|
||||
}
|
||||
|
||||
/** \ingroup INTERNALS
|
||||
* \brief Read a complete cluster
|
||||
* \param d FSDIRENTRY pointer. CurrentCluster is used
|
||||
* \return FS_SUCCESS on success
|
||||
*/
|
||||
static int ReadCluster( FSDIRENTRY *d )
|
||||
{
|
||||
int sector;
|
||||
|
||||
sector = SectorFromCluster( d->driveid, d->CurrentCluster );
|
||||
if ( DISKIO_ReadSectors( d->driveid, d->clusterdata, sector, vfs[d->driveid]->SectorsPerCluster) != FS_SUCCESS )
|
||||
return FS_ERR_IO;
|
||||
|
||||
d->CachedCluster = d->CurrentCluster;
|
||||
return FS_SUCCESS;
|
||||
}
|
||||
|
||||
/** \ingroup INTERNALS
|
||||
* \brief Update entry with next cluster in chain
|
||||
* \param d FSDIRENTRY pointer. CurrentCluster is used
|
||||
* \return True on success
|
||||
*/
|
||||
static int NextCluster( FSDIRENTRY *d )
|
||||
{
|
||||
d->CurrentCluster = SWAP16(vfs[d->driveid]->FAT[d->CurrentCluster]);
|
||||
if ( d->CurrentCluster >= CLUSTER_END_CHAIN )
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* FindEntry
|
||||
*
|
||||
* Look through a directory tree looking for an active entry.
|
||||
* The current cluster should be available in d->clusterdata
|
||||
****************************************************************************/
|
||||
/** \ingroup INTERNALS
|
||||
* \param d FSDIRENTRY pointer
|
||||
* \param maxentries Maximum directory entries held in cluster
|
||||
* \return True if found, False if not found
|
||||
*/
|
||||
static int FindEntry( FSDIRENTRY *d, int maxentries )
|
||||
{
|
||||
int found = 0;
|
||||
unsigned char *direntry;
|
||||
VFATFS *v = vfs[d->driveid];
|
||||
SFNDIRREC *sfn;
|
||||
LFNDIRREC *lfn;
|
||||
static BYTE checksum = 0;
|
||||
|
||||
if ( !d->crosscluster )
|
||||
{
|
||||
/* Clear names */
|
||||
memset(d->shortname, 0, 13);
|
||||
memset(d->longname, 0, MAX_LONG_NAME);
|
||||
}
|
||||
|
||||
while( d->CurrentDirEntry < maxentries && !found )
|
||||
{
|
||||
/* Pointer to this directory entry */
|
||||
if ( d->CurrentCluster == ROOTCLUSTER )
|
||||
direntry = (v->rootDir + ( d->CurrentDirEntry << 5 ) );
|
||||
else
|
||||
direntry = (d->clusterdata + ( d->CurrentDirEntry << 5 ) );
|
||||
|
||||
switch( direntry[0] )
|
||||
{
|
||||
case 0x00:
|
||||
case 0xE5:
|
||||
break; /* Inactive entries */
|
||||
|
||||
default:
|
||||
|
||||
sfn = (SFNDIRREC *)direntry;
|
||||
d->crosscluster = 1;
|
||||
|
||||
if ( ( sfn->attribute & ATTR_LONG_NAME_MASK ) == ATTR_LONG_NAME )
|
||||
{
|
||||
if ( direntry[0] & LFN_LAST_ENTRY )
|
||||
memset(&d->longname, 0, MAX_LONG_NAME);
|
||||
|
||||
lfn = (LFNDIRREC *)direntry;
|
||||
BuildLongNameFromDirEntry( lfn, direntry[0] & LFN_ENTRY_MASK, d->longname);
|
||||
checksum = lfn->checksum;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Short name entry */
|
||||
found = 1;
|
||||
memcpy(&d->dirent, direntry, 32);
|
||||
BuildShortNameFromDirEntry( sfn, d->shortname );
|
||||
d->fsize = SWAP32(sfn->filesize);
|
||||
d->crosscluster = 0;
|
||||
/* Ensure long name is populated with something */
|
||||
if ( strlen((char *)d->longname) == 0 )
|
||||
{
|
||||
strcpy((char *)d->longname, (char *)d->shortname);
|
||||
return found;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If checksums don't match - the FS is inconsistent
|
||||
To do no harm, skip this entry */
|
||||
if ( checksum == CalcShortNameCheckSum(sfn->dirname) )
|
||||
return found;
|
||||
else
|
||||
found = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d->CurrentDirEntry++;
|
||||
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* FindInRootDirectory
|
||||
*
|
||||
* Root directory is somewhat special. It's a fixed length and has no entry
|
||||
* in the FAT as such.
|
||||
*
|
||||
* Logically, this should be the first 2 clusters, but the spec says it can
|
||||
* be set to any size by the format utility (Think NT! FAT64/128/256)
|
||||
*
|
||||
* For speed, as all searches begin here, the root directory is held in
|
||||
* memory throughout.
|
||||
*
|
||||
* FSDIRENTRY should only have the drive id set.
|
||||
****************************************************************************/
|
||||
/** \ingroup INTERNALS
|
||||
* \brief Find an entry in the root directory
|
||||
* \param d FSDIRENTRY pointer
|
||||
* \param search Name to find
|
||||
* \return True if found, False if not
|
||||
*/
|
||||
static int FindInRootDirectory( FSDIRENTRY *d, char *search )
|
||||
{
|
||||
int found = 0;
|
||||
|
||||
d->CurrentDirEntry++;
|
||||
|
||||
while( (FindEntry(d, vfs[d->driveid]->RootDirEntries)) && !found )
|
||||
{
|
||||
if ( strcasecmp(search, (char *) d->shortname) == 0 )
|
||||
{
|
||||
found = 1;
|
||||
}
|
||||
|
||||
if ( strcasecmp(search, (char *) d->longname) == 0 )
|
||||
{
|
||||
found = 1;
|
||||
}
|
||||
|
||||
if ( !found )
|
||||
d->CurrentDirEntry++;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* FindInClusters
|
||||
*
|
||||
* Generic routine to find a given name in a chain of clusters.
|
||||
* Used for non-Root Directory searching
|
||||
****************************************************************************/
|
||||
/** \ingroup INTERNALS
|
||||
* \brief Find a directory record in a cluster chain
|
||||
* \param d FSDIRENTRY pointer
|
||||
* \param findme Name of directory record to find
|
||||
* \return True if found, False if not
|
||||
*/
|
||||
static int FindInClusters( FSDIRENTRY *d, char *findme )
|
||||
{
|
||||
int found = 0;
|
||||
|
||||
if ( d->CurrentDirEntry == -1 )
|
||||
d->CurrentDirEntry = 0;
|
||||
|
||||
/* While not at end of chain */
|
||||
while( !found && ( d->CurrentCluster < CLUSTER_END_CHAIN ) )
|
||||
{
|
||||
/* Retrieve dir entries looking for match */
|
||||
while( !found && (FindEntry( d, ( vfs[d->driveid]->BytesPerSector * vfs[d->driveid]->SectorsPerCluster) >> 5 ) ) )
|
||||
{
|
||||
if ( strcasecmp((char *)d->shortname, findme) == 0 )
|
||||
found = 1;
|
||||
if ( strcasecmp((char *)d->longname, findme) == 0 )
|
||||
found = 1;
|
||||
|
||||
if (!found)
|
||||
d->CurrentDirEntry++;
|
||||
}
|
||||
|
||||
/* Read next cluster */
|
||||
if ( !found )
|
||||
{
|
||||
if ( NextCluster(d) )
|
||||
{
|
||||
d->CurrentDirEntry = 0;
|
||||
ReadCluster(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* VFAT_opendir
|
||||
*
|
||||
* Find the requested directory.
|
||||
****************************************************************************/
|
||||
int VFAT_opendir( int drive, FSDIRENTRY *d, char *search )
|
||||
{
|
||||
char *p;
|
||||
char srchtmp[1024];
|
||||
int searchroot = 1;
|
||||
int found = 0;
|
||||
|
||||
/* Clear out FSDIRENTRY */
|
||||
memset(d, 0, sizeof(FSDIRENTRY));
|
||||
|
||||
/* Set drive and root */
|
||||
d->driveid = drive;
|
||||
d->CurrentCluster = ROOTCLUSTER;
|
||||
d->CurrentDirEntry = -1;
|
||||
|
||||
/* Is this a request for root ? */
|
||||
if ( ( strlen(search) == 0 ) || ( strcmp(search,PSEPS) == 0 ) || ( strcmp(search, DIR_ROOT) == 0 ) )
|
||||
{
|
||||
return FS_FILE_OK;
|
||||
}
|
||||
|
||||
/* Searching for a sub-directory */
|
||||
if ( search[0] == PSEP )
|
||||
strcpy(srchtmp, &search[1]);
|
||||
else
|
||||
strcpy(srchtmp, search);
|
||||
|
||||
p = strtok(srchtmp, PSEPS);
|
||||
while ( p )
|
||||
{
|
||||
found = 0;
|
||||
if ( searchroot )
|
||||
{
|
||||
if ( !FindInRootDirectory(d, p) )
|
||||
return FS_NO_FILE;
|
||||
else
|
||||
{
|
||||
/* MUST be a directory */
|
||||
if ( d->dirent.attribute & ATTR_DIRECTORY )
|
||||
{
|
||||
d->CurrentCluster = d->FirstCluster = SWAP16(d->dirent.fstClustLow);
|
||||
d->CurrentDirEntry = -1;
|
||||
|
||||
/* Allocate the cluster for this data record */
|
||||
d->clusterdata = (BYTE *)malloc(vfs[d->driveid]->SectorsPerCluster * vfs[d->driveid]->BytesPerSector);
|
||||
ReadCluster(d);
|
||||
found = 1;
|
||||
searchroot = 0;
|
||||
}
|
||||
else
|
||||
return FS_NO_FILE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( FindInClusters( d, p ) )
|
||||
{
|
||||
/* MUST be a directory */
|
||||
if ( !( d->dirent.attribute & ATTR_DIRECTORY ) )
|
||||
{
|
||||
free(d->clusterdata);
|
||||
return FS_NO_FILE;
|
||||
}
|
||||
|
||||
/* Read up this cluster */
|
||||
d->CurrentCluster = d->FirstCluster = SWAP16(d->dirent.fstClustLow);
|
||||
d->CurrentDirEntry = 0;
|
||||
ReadCluster(d);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
p = strtok(NULL, PSEPS);
|
||||
}
|
||||
|
||||
if ( !found )
|
||||
{
|
||||
if ( d->clusterdata != NULL )
|
||||
{
|
||||
free(d->clusterdata);
|
||||
d->clusterdata = NULL;
|
||||
}
|
||||
return FS_NO_FILE;
|
||||
}
|
||||
|
||||
return FS_FILE_OK;
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* VFAT_readdir
|
||||
****************************************************************************/
|
||||
int VFAT_readdir( FSDIRENTRY *d )
|
||||
{
|
||||
int ret;
|
||||
|
||||
d->CurrentDirEntry++;
|
||||
/* Are we in root ? */
|
||||
if ( d->CurrentCluster == ROOTCLUSTER )
|
||||
{
|
||||
if( FindEntry( d, vfs[d->driveid]->RootDirEntries ) )
|
||||
return FS_FILE_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
while( d->CurrentCluster < CLUSTER_END_CHAIN )
|
||||
{
|
||||
ret = FindEntry( d, ( vfs[d->driveid]->BytesPerSector * vfs[d->driveid]->SectorsPerCluster) >> 5 );
|
||||
|
||||
if ( ret )
|
||||
return FS_FILE_OK;
|
||||
|
||||
if ( NextCluster(d) )
|
||||
{
|
||||
d->CurrentDirEntry = 0;
|
||||
ReadCluster(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
return FS_NO_FILE;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* VFAT_closedir
|
||||
****************************************************************************/
|
||||
void VFAT_closedir( FSDIRENTRY *d )
|
||||
{
|
||||
if ( d->clusterdata != NULL )
|
||||
{
|
||||
free(d->clusterdata);
|
||||
d->clusterdata = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* VFAT_fopen
|
||||
*
|
||||
* v0.1 - VFAT_READ_ONLY Supported
|
||||
****************************************************************************/
|
||||
int VFAT_fopen( int drive, FSDIRENTRY *d, char *fname, int mode )
|
||||
{
|
||||
char filename[1024];
|
||||
char path[1024];
|
||||
char temp[1024];
|
||||
char *p;
|
||||
|
||||
if ( drive < 0 || drive > 1 )
|
||||
return FS_NO_FILE;
|
||||
|
||||
if ( mode != FS_READ )
|
||||
return FS_NO_FILE;
|
||||
|
||||
/* Clear */
|
||||
memset(d, 0, sizeof(FSDIRENTRY));
|
||||
d->driveid = drive;
|
||||
|
||||
path[0] = temp[0] = filename[0] = 0;
|
||||
|
||||
if ( fname[0] == PSEP )
|
||||
strcpy(temp, &fname[1]);
|
||||
else
|
||||
strcpy(temp, fname);
|
||||
|
||||
/* Split into filename and path */
|
||||
p = strrchr(temp, PSEP);
|
||||
if ( p )
|
||||
{
|
||||
/* Have path and filename */
|
||||
*p = 0;
|
||||
strcpy(path, temp);
|
||||
p++;
|
||||
strcpy(filename, p);
|
||||
}
|
||||
else
|
||||
strcpy(filename, temp);
|
||||
|
||||
/* Do search */
|
||||
if ( strlen(path) )
|
||||
{
|
||||
if ( VFAT_opendir(drive, d, path) != FS_FILE_OK )
|
||||
{
|
||||
VFAT_closedir(d);
|
||||
return FS_NO_FILE;
|
||||
}
|
||||
|
||||
if ( !FindInClusters( d, filename ) )
|
||||
{
|
||||
VFAT_closedir(d);
|
||||
return FS_NO_FILE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Much simpler check on root directory */
|
||||
d->CurrentCluster = ROOTCLUSTER;
|
||||
d->CurrentDirEntry = -1;
|
||||
if ( !FindInRootDirectory( d, filename ) )
|
||||
{
|
||||
VFAT_closedir(d);
|
||||
return FS_NO_FILE;
|
||||
}
|
||||
d->clusterdata = (BYTE *)malloc(vfs[d->driveid]->SectorsPerCluster * vfs[d->driveid]->BytesPerSector);
|
||||
}
|
||||
|
||||
/* Must be a file only */
|
||||
if ( d->dirent.attribute & ( ATTR_DIRECTORY | ATTR_VOLUME_ID ) )
|
||||
{
|
||||
VFAT_closedir(d);
|
||||
return FS_NO_FILE;
|
||||
}
|
||||
|
||||
d->FirstCluster = d->CurrentCluster = SWAP16(d->dirent.fstClustLow);
|
||||
d->CachedCluster = -1;
|
||||
|
||||
return FS_FILE_OK;
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* VFAT_fclose
|
||||
****************************************************************************/
|
||||
void VFAT_fclose( FSDIRENTRY *d )
|
||||
{
|
||||
VFAT_closedir(d);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* VFAT_fread
|
||||
****************************************************************************/
|
||||
int VFAT_fread( FSDIRENTRY *d, void *buffer, int length )
|
||||
{
|
||||
int cluster;
|
||||
int tbytes;
|
||||
int umask;
|
||||
int i;
|
||||
int bytesdone = 0;
|
||||
int reallength;
|
||||
BYTE *p = (BYTE *)buffer;
|
||||
|
||||
if ( length <= 0 )
|
||||
return 0;
|
||||
|
||||
/* Determine which cluster in the chain we are in */
|
||||
tbytes = ( vfs[d->driveid]->SectorsPerCluster * vfs[d->driveid]->BytesPerSector );
|
||||
umask = tbytes - 1;
|
||||
cluster = ( d->fpos / tbytes );
|
||||
|
||||
/* Rewind current cluster */
|
||||
d->CurrentCluster = d->FirstCluster;
|
||||
|
||||
/* Bring this cluster into view */
|
||||
for ( i = 0; i < cluster; i++ )
|
||||
d->CurrentCluster = SWAP16(vfs[d->driveid]->FAT[d->CurrentCluster]);
|
||||
|
||||
/* Read the cluster */
|
||||
if ( d->CachedCluster != d->CurrentCluster )
|
||||
ReadCluster(d);
|
||||
|
||||
/* Get real read length */
|
||||
reallength = ( d->fpos + length ) < d->fsize ? length : d->fsize - d->fpos;
|
||||
|
||||
if ( reallength <= 0 )
|
||||
return 0;
|
||||
|
||||
/* Move data */
|
||||
while( reallength )
|
||||
{
|
||||
if ( !(d->fpos & umask) && ( reallength >= tbytes ) )
|
||||
{
|
||||
/* Move a full cluster */
|
||||
memcpy(p + bytesdone, d->clusterdata, tbytes);
|
||||
reallength -= tbytes;
|
||||
bytesdone += tbytes;
|
||||
d->fpos += tbytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
p[bytesdone++] = d->clusterdata[d->fpos & umask];
|
||||
d->fpos++;
|
||||
reallength--;
|
||||
}
|
||||
|
||||
if ( !( d->fpos & umask ) )
|
||||
{
|
||||
if ( NextCluster(d) )
|
||||
{
|
||||
ReadCluster(d);
|
||||
}
|
||||
else
|
||||
return bytesdone;
|
||||
}
|
||||
}
|
||||
|
||||
return bytesdone;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* VFAT_fseek
|
||||
****************************************************************************/
|
||||
int VFAT_fseek( FSDIRENTRY *d, int where, int whence )
|
||||
{
|
||||
switch( whence )
|
||||
{
|
||||
case SEEK_SET:
|
||||
if ( ( where >= 0 ) && ( where <= d->fsize ) )
|
||||
{
|
||||
d->fpos = where;
|
||||
return FS_FILE_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
if ( ( ( d->fpos + where ) >= 0 ) && ( ( d->fpos + where ) <= d->fsize ) )
|
||||
{
|
||||
d->fpos += where;
|
||||
return FS_FILE_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
if ( ( where <= 0 ) && ( abs(where) <= d->fsize ) )
|
||||
{
|
||||
d->fpos = d->fsize + where;
|
||||
return FS_FILE_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FS_NO_FILE;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* VFAT_ftell
|
||||
*
|
||||
* Return the current position of a file
|
||||
****************************************************************************/
|
||||
int VFAT_ftell( FSDIRENTRY *d )
|
||||
{
|
||||
return d->fpos;
|
||||
}
|
||||
|
@ -1,364 +0,0 @@
|
||||
/****************************************************************************
|
||||
* FAT16 - VFAT Support
|
||||
*
|
||||
* NOTE: Only supports FAT16 with Long File Names
|
||||
* I have no interest in adding FAT32
|
||||
*
|
||||
* Reference Documentation:
|
||||
*
|
||||
* FAT: General Overview of On-Disk Format
|
||||
* Version 1.02 May 05, 1999
|
||||
* Microsoft Corporation
|
||||
*
|
||||
* FAT: General Overview of On-Disk Format
|
||||
* Version 1.03 December 06, 2000
|
||||
* Microsoft Corporation
|
||||
*
|
||||
* This is targetted at MMC/SD cards.
|
||||
*
|
||||
* Copyright softdev 2007. All rights reserved.
|
||||
*
|
||||
* $Date: 2007-08-05 14:27:48 +0100 (Sun, 05 Aug 2007) $
|
||||
* $Rev: 8 $
|
||||
****************************************************************************/
|
||||
#ifndef __FATVFAT__
|
||||
#define __FATVFAT__
|
||||
|
||||
#include "integer.h"
|
||||
|
||||
/* x86 type definitions */
|
||||
/**\typedef VDWORD
|
||||
* Unsigned 32 bit integer
|
||||
*/
|
||||
typedef unsigned int VDWORD;
|
||||
/**\typedef WORD
|
||||
* Unsigned 16 bit short
|
||||
*/
|
||||
//typedef unsigned short WORD;
|
||||
/**\typedef BYTE
|
||||
* Unsigned 8 bit char
|
||||
*/
|
||||
//typedef unsigned char BYTE;
|
||||
|
||||
/* Big Endian Support */
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define SWAP16(a) (((a&0xff)<<8) | ((a&0xff00)>>8))
|
||||
#define SWAP32(a) (((a&0xff000000)>>24) | ((a&0xff0000) >> 8) | ((a&0xff00)<<8) |((a&0xff)<<24))
|
||||
#else
|
||||
#define SWAP16(a) (a)
|
||||
#define SWAP32(a) (a)
|
||||
#endif
|
||||
|
||||
/* General */
|
||||
/**\def SECTOR_SIZE
|
||||
* Set to sector size of device\n
|
||||
* Default is 512, which is suitable for most SD cards\n
|
||||
* All sector sizes must be a power of 2
|
||||
*/
|
||||
#define SECTOR_SIZE 512 /* Default sector is 512 bytes */
|
||||
/**\def SECTOR_SHIFT_BITS
|
||||
* Number of shift bits for faster multiplication and division
|
||||
*/
|
||||
#define SECTOR_SHIFT_BITS 9 /* Sector shift bits */
|
||||
#define LFN_LAST_ENTRY 0x40 /* Long File Name last entry mask */
|
||||
#define LFN_ENTRY_MASK 0x3F /* Long File Name entry number mask */
|
||||
#define ROOTCLUSTER 0xdeadc0de /* Unique root directory cluster id */
|
||||
|
||||
/**\def PSEP
|
||||
* Path separator. Default unix style /
|
||||
*/
|
||||
#define PSEP '/' /* Path separator. Default unix / */
|
||||
/**\def PSEPS
|
||||
* Path separator string. Default unix style /
|
||||
*/
|
||||
#define PSEPS "/" /* Path separator string. Default unix / */
|
||||
|
||||
#define DIR_ROOT "." /* Root directory entry */
|
||||
#define DIR_PARENT ".." /* Parent directory entry */
|
||||
|
||||
/* FSTYPES */
|
||||
#define FS_TYPE_NONE 0
|
||||
#define FS_TYPE_FAT16 1
|
||||
|
||||
/* Errors */
|
||||
#define FS_FILE_OK 0
|
||||
#define FS_SUCCESS FS_FILE_OK
|
||||
#define FS_ERR_NOMEM -128
|
||||
#define FS_NO_FILE -64
|
||||
#define FS_ERR_IO -32
|
||||
#define FS_ERR_PARAM -16
|
||||
|
||||
/* File modes */
|
||||
#define FS_READ 1
|
||||
|
||||
/* Gamecube Specific */
|
||||
#define FS_SLOTA 0
|
||||
#define FS_SLOTB 1
|
||||
|
||||
/* FAT12/16 */
|
||||
typedef struct
|
||||
{
|
||||
BYTE jmpBoot[3]; /**< Always 0xEBxx90 or 0xE9xxxx */
|
||||
BYTE OEMName[8]; /**< OEM Name 'MSWIN4.1' or similar */
|
||||
WORD bytesPerSec; /**< Bytes per sector */
|
||||
BYTE secPerClust; /**< Sectors per cluster */
|
||||
WORD reservedSec; /**< Reserved Sector Count */
|
||||
BYTE numFATs; /**< Number of FAT copies */
|
||||
WORD rootEntCount; /**< FAT12/16 number of root entries. */
|
||||
WORD totSec16; /**< Sector count if < 0x10000 */
|
||||
BYTE media; /**< Media ID byte (HD == 0xF8) */
|
||||
WORD FATsz16; /**< Sectors occupied by one copy of FAT */
|
||||
WORD secPerTrack; /**< Sectors per track */
|
||||
WORD numHeads; /**< Number of heads */
|
||||
VDWORD hiddenSec; /**< Hidden sector count */
|
||||
VDWORD totSec32; /**< Total sectors when >= 0x10000 */
|
||||
BYTE drvNum; /**< BIOS Drive Number (0x80) */
|
||||
BYTE reserved1; /**< Unused - always zero */
|
||||
BYTE bootSig; /**< Boot signature */
|
||||
VDWORD volID; /**< Volume serial number */
|
||||
BYTE volName[11]; /**< Volume Name */
|
||||
BYTE FilSysType[8]; /**< File system type */
|
||||
BYTE filler[SECTOR_SIZE-64]; /**< Byte padding */
|
||||
BYTE sigkey1; /**< 0x55 */
|
||||
BYTE sigkey2; /**< 0xAA */
|
||||
}
|
||||
#ifndef DOXYGEN_FIX_ATTR
|
||||
__attribute__((__packed__))
|
||||
#endif
|
||||
BPB16;
|
||||
|
||||
/* Partition entry */
|
||||
typedef struct
|
||||
{
|
||||
BYTE bootindicator; /**< Boot indicator 00 == No 0x80 == Boot */
|
||||
BYTE startCHS[3]; /**< Start Cylinder / Head / Sector */
|
||||
BYTE partitiontype; /**< Partition Type. ID 06 FAT 16 */
|
||||
BYTE endCHS[3]; /**< End Cylinder / Head / Sector */
|
||||
VDWORD partitionstart; /**< LBA Start Sector */
|
||||
VDWORD partitionsize; /**< Partition size in sectors */
|
||||
}
|
||||
#ifndef DOXYGEN_FIX_ATTR
|
||||
__attribute__((__packed__))
|
||||
#endif
|
||||
PARTENTRY;
|
||||
|
||||
/* VFAT - Main structure */
|
||||
typedef struct
|
||||
{
|
||||
VDWORD BaseOffset; /**< Offset in sectors to BPB */
|
||||
VDWORD SectorsPerCluster; /**< Sectors per cluster (Native) */
|
||||
VDWORD BytesPerSector; /**< Bytes per sector (Native) */
|
||||
VDWORD ReservedSectors; /**< Reserved sectors (Native) */
|
||||
VDWORD RootDirSectors; /**< Root directory sectors (Native) */
|
||||
VDWORD SectorsPerFAT; /**< Sectors per FAT (Native) */
|
||||
VDWORD NumberOfFATs; /**< Number of FAT copies (Native) */
|
||||
VDWORD FirstDataSector; /**< First data sector offset (Native) */
|
||||
VDWORD TotalSectors; /**< Total sectors (Native) */
|
||||
VDWORD CountOfClusters; /**< Count of clusters (Native) */
|
||||
VDWORD DataSectors; /**< Number of Data sectors (Native) */
|
||||
VDWORD RootDirOffset; /**< Offset of root directory (Native) */
|
||||
VDWORD FirstFATOffset; /**< Offset to first copy of FAT (Native) */
|
||||
VDWORD RootDirEntries; /**< Number of root directory entries (Native) */
|
||||
WORD *FAT; /**< Holds first FAT copy */
|
||||
BYTE *rootDir; /**< Holds entire root directory */
|
||||
}
|
||||
#ifndef DOXYGEN_FIX_ATTR
|
||||
__attribute__((__packed__))
|
||||
#endif
|
||||
VFATFS;
|
||||
|
||||
/*
|
||||
* Directory Functions
|
||||
*/
|
||||
|
||||
#define MAX_LONG_NAME 256
|
||||
|
||||
/* Directory entry attributes */
|
||||
#define ATTR_READ_ONLY 0x01
|
||||
#define ATTR_HIDDEN 0x02
|
||||
#define ATTR_SYSTEM 0x04
|
||||
#define ATTR_VOLUME_ID 0x08
|
||||
#define ATTR_DIRECTORY 0x10
|
||||
#define ATTR_ARCHIVE 0x20
|
||||
#define ATTR_LONG_NAME (ATTR_READ_ONLY | \
|
||||
ATTR_HIDDEN | \
|
||||
ATTR_SYSTEM | \
|
||||
ATTR_VOLUME_ID )
|
||||
|
||||
#define ATTR_LONG_NAME_MASK ( ATTR_READ_ONLY | \
|
||||
ATTR_HIDDEN | \
|
||||
ATTR_SYSTEM | \
|
||||
ATTR_VOLUME_ID | \
|
||||
ATTR_DIRECTORY | \
|
||||
ATTR_ARCHIVE )
|
||||
|
||||
/**\def CLUSTER_END_CHAIN
|
||||
* Any value equal or greater than 0xFFF8 should be
|
||||
* considered an end of chain marker.
|
||||
*/
|
||||
#define CLUSTER_END_CHAIN 0xFFF8
|
||||
|
||||
/**\def CLUSTER_BAD
|
||||
* Documentation states that any BAD or unusable sector should be marked\n
|
||||
* as 0xFFF7.
|
||||
*/
|
||||
#define CLUSTER_BAD 0xFFF7
|
||||
|
||||
/* Short file name */
|
||||
typedef struct
|
||||
{
|
||||
BYTE dirname[11]; /**< Record name */
|
||||
BYTE attribute; /**< Attributes */
|
||||
BYTE NTReserved; /**< Reserved for Windows NT - set 0 */
|
||||
BYTE dirTenthSecs; /**< Tenth of a second, 0-199 */
|
||||
WORD dirCreateTime; /**< Time of creation */
|
||||
WORD dirCreateDate; /**< Date of creation */
|
||||
WORD dirLastAccDate;/**< Date of last access */
|
||||
WORD fstClustHigh; /**< High word of first cluster - ZERO on FAT16 (LE)*/
|
||||
WORD dirWriteTime; /**< Time of last write */
|
||||
WORD dirWriteDate; /**< Date of last write */
|
||||
WORD fstClustLow; /**< Low word of first cluster (LE)*/
|
||||
VDWORD filesize; /**< Filesize in bytes (LE)*/
|
||||
}
|
||||
#ifndef DOXYGEN_FIX_ATTR
|
||||
__attribute__((__packed__))
|
||||
#endif
|
||||
SFNDIRREC;
|
||||
|
||||
/* Long file name */
|
||||
typedef struct
|
||||
{
|
||||
BYTE ordinal; /**< Entry number (0x4x) == Last entry */
|
||||
BYTE dirname1[10]; /**< First part of filename in unicode */
|
||||
BYTE attribute; /**< Attributes - MUST be ATTR_LONG_NAME (0x0F) */
|
||||
BYTE type; /**< Reserved */
|
||||
BYTE checksum; /**< SFN Checksum */
|
||||
BYTE dirname2[12]; /**< Second part of filename in unicode */
|
||||
WORD fstClustLo; /**< MUST BE ZERO! */
|
||||
BYTE dirname3[4]; /**< Third part of filename in unicode */
|
||||
}
|
||||
#ifndef DOXYGEN_FIX_ATTR
|
||||
__attribute__((__packed__))
|
||||
#endif
|
||||
LFNDIRREC;
|
||||
|
||||
/* User dir entry */
|
||||
typedef struct
|
||||
{
|
||||
BYTE longname[MAX_LONG_NAME]; /**< Long file name, application friendly */
|
||||
BYTE shortname[13]; /**< Short file name, application friendly */
|
||||
VDWORD fpos; /**< Current file position */
|
||||
VDWORD fsize; /**< File size in bytes (Native) */
|
||||
VDWORD driveid; /**< Device number */
|
||||
VDWORD FirstCluster; /**< First cluster in chain (Native) */
|
||||
VDWORD CurrentCluster; /**< Current cluster in chain (Native) */
|
||||
VDWORD CachedCluster; /**< Cached cluster (Native) */
|
||||
VDWORD CurrentDirEntry; /**< Current directory entry in current cluster (Native) */
|
||||
VDWORD crosscluster; /**< Record crosses cluster boundary */
|
||||
BYTE *clusterdata; /**< Cluster data */
|
||||
/* Now a copy of the current directory entry */
|
||||
SFNDIRREC dirent; /**< Copy of physical SFNDIRREC */
|
||||
}
|
||||
#ifndef DOXYGEN_FIX_ATTR
|
||||
__attribute__((__packed__))
|
||||
#endif
|
||||
FSDIRENTRY;
|
||||
|
||||
/* VFAT API */
|
||||
/** \defgroup VFATDir VFATFS Directory Level Functions
|
||||
* \brief VFAT FS Directory Functions
|
||||
*/
|
||||
|
||||
/* Directory */
|
||||
|
||||
/** \ingroup VFATDir
|
||||
* \brief Open a directory
|
||||
* \param drive Device number to use
|
||||
* \param d Pointer to user provided FSDIRENTRY
|
||||
* \param search Path to open
|
||||
* \return FS_SUCCESS if succesful
|
||||
*/
|
||||
int VFAT_opendir( int drive, FSDIRENTRY *d, char *search );
|
||||
|
||||
/** \ingroup VFATDir
|
||||
* \brief Read directory entries
|
||||
* \param d Pointer to user provided FSDIRENTRY, previously populated from VFAT_opendir
|
||||
* \return FS_SUCCESS if successful
|
||||
*/
|
||||
int VFAT_readdir( FSDIRENTRY *d );
|
||||
|
||||
/** \ingroup VFATDir
|
||||
* \brief Close a previously opened directory
|
||||
* \param d Pointer to user provided FSDIRENTRY, previously populated from VFAT_opendir
|
||||
* \return None.
|
||||
*/
|
||||
void VFAT_closedir( FSDIRENTRY *d );
|
||||
|
||||
/** \defgroup VFATFile VFATFS File Level Functions
|
||||
* \brief VFAT FS File functions
|
||||
*/
|
||||
|
||||
/** \ingroup VFATFile
|
||||
* \brief Open a file
|
||||
* \param drive Device number to use
|
||||
* \param d Pointer to user provided FSDIRENTRY
|
||||
* \param fname Filename, including full path, to open
|
||||
* \param mode Currently only FS_READ is supported
|
||||
* \return FS_SUCCESS if successful.
|
||||
*/
|
||||
int VFAT_fopen( int drive, FSDIRENTRY *d, char *fname, int mode );
|
||||
|
||||
/** \ingroup VFATFile
|
||||
* \brief Close a previously opened file
|
||||
* \param d Pointer to user provided FSDIRENTRY, previously populated by VFAT_fopen
|
||||
* \return None.
|
||||
*/
|
||||
void VFAT_fclose( FSDIRENTRY *d );
|
||||
|
||||
/** \ingroup VFATFile
|
||||
* \brief Read from an open file
|
||||
* \param d Pointer to user provided FSDIRENTRY, populated by a successful call to VFAT_fopen
|
||||
* \param buffer Buffer to receive data
|
||||
* \param length Number of bytes to read to the buffer
|
||||
* \return Number of bytes read if positive. If <0 an error has occurred.
|
||||
*/
|
||||
int VFAT_fread( FSDIRENTRY *d, void *buffer, int length );
|
||||
|
||||
/** \ingroup VFATFile
|
||||
* \brief Return the current file position
|
||||
* \param d Pointer to user provided FSDIRENTRY
|
||||
* \return Current file position
|
||||
*/
|
||||
int VFAT_ftell( FSDIRENTRY *d );
|
||||
|
||||
/** \ingroup VFATFile
|
||||
* \brief Move current file pointer to the requested position
|
||||
* \param d Pointer to user provided FSDIRENTRY
|
||||
* \param where New byte position
|
||||
* \param whence Define movement type. SEEK_SET, SEEK_END and SEEK_CUR are supported
|
||||
* \return FS_SUCCESS if successful
|
||||
*/
|
||||
int VFAT_fseek( FSDIRENTRY *d, int where, int whence );
|
||||
|
||||
/** \defgroup VFATMount VFATFS Device Mount Functions
|
||||
* \brief Device mount / unmount functions
|
||||
*/
|
||||
|
||||
/** \ingroup VFATMount
|
||||
* \brief Mount a device
|
||||
* \param driveid Device number to mount
|
||||
* \param v Pointer to user provided VFATFS
|
||||
* \return FS_TYPE_FAT16 on success.
|
||||
*/
|
||||
int VFAT_mount( int driveid, VFATFS *v );
|
||||
|
||||
/** \ingroup VFATMount
|
||||
* \brief Unmount a device
|
||||
* \param driveid Device drive number
|
||||
* \param v Pointer to user provided VFATFS
|
||||
* \return None
|
||||
*/
|
||||
void VFAT_unmount( int driveid, VFATFS *v );
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user