port to libfat / devkitpro r15

This commit is contained in:
dsbomb 2008-06-06 14:10:34 +00:00
parent 05448c1115
commit 6f1dea5b2d
24 changed files with 367 additions and 5354 deletions

View File

@ -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

View File

@ -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
#---------------------------------------------------------------------------------

View File

@ -1,4 +0,0 @@
cp Makefile.orig Makefile
make
rm Makefile
rm -d build/*.*

View File

@ -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 )

View File

@ -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 )

View File

@ -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 (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);
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);
// 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;
}
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);
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++;
}
}
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 (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,83 +797,27 @@ 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() {
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();
@ -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;
}
filehandle = SDCARD_OpenFile (fname, "rb");
if (filehandle == NULL)
{
WaitPrompt ("Unable to open file!");
return;
dirclose(dir);
}
rootdirlength = SDCARD_GetFileSize (filehandle);
}

View File

@ -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];

View File

@ -45,36 +45,28 @@ 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++)
w += font_width;
return w;
}
int CentreTextPosition( char *text )
{
int CentreTextPosition(char *text) {
return ((640 - GetTextWidth(text)) >> 1);
}
void WriteCentre( int y, char *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) && (quit == 0)) {
ClearScreen();
WriteCentre(220, msg);
WriteCentre(220 + font_height, MENU_PRESS_A);
@ -88,14 +80,11 @@ 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 (1) {
btns = PAD_ButtonsDown (0);
if (btns & PAD_BUTTON_A)
return 1;
@ -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,8 +109,7 @@ 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);
@ -132,8 +119,7 @@ void ShowAction( char *msg )
/****************************************************************************
* GX Chip Copy to XFB
****************************************************************************/
static void copy_to_xfb()
{
static void copy_to_xfb() {
if (copynow == GX_TRUE) {
GX_CopyDisp(xfb[whichfb],GX_TRUE);
GX_Flush();
@ -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,9 +189,7 @@ 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;
@ -218,11 +200,9 @@ void GXDraw( unsigned char *XBuf )
/*** 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,25 +295,19 @@ 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) {
case 0 :
VIDEO_ClearFrameBuffer(vmode, xfb[whichfb], COLOR_BLACK);
/*** Simply go through each row ***/
for( h = 0; h < NESHEIGHT; h++ )
{
for( w = 0; w < NESWIDTH; 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
@ -400,8 +342,7 @@ void RenderFrame( char *XBuf, int style )
****************************************************************************/
unsigned int rgbcolor(unsigned char r1, unsigned char g1, unsigned char b1,
unsigned char r2, unsigned char g2, unsigned char b2)
{
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;
@ -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;
@ -443,8 +384,8 @@ void FCEUD_SetPalette(unsigned char index, unsigned char r, unsigned char g, uns
/****************************************************************************
* 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];
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++ )
{
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
{
} else {
xfb[whichfb][ofs + nw] = gcpalette[newrow[nw]];
xfb[whichfb][ofs + nw + 320] = gcpalette[newrow[nw]];
}
}
gcdispOffset += 640;
}
}
}

View File

@ -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,8 +73,7 @@ static inline u16 FLIP16(u16 b)
* it is populated before calling.
****************************************************************************/
bool isZipFile()
{
bool isZipFile() {
u32 check;
memcpy(&check, &readbuffer, 4);
@ -100,8 +89,7 @@ bool isZipFile()
* Unzip terminates on Z_END_STREAM.
***************************************************************************/
int unzipDVDFile(unsigned char *outbuffer,
unsigned int discoffset, unsigned int length)
{
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;
@ -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 ) )

View File

@ -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;
case MEDIA_SLOT:
ChosenSlot++;
if (ChosenSlot >= SdSlotCount)
ChosenSlot = 0;
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
case MEDIA_STOPDVD:
ShowAction((char*)MENU_MEDIA_STOPPING);
dvd_motor_off();
WaitPrompt((char*)MENU_MEDIA_STOPPED);
break;
case MEDIA_EXIT:
quit = 1;
break;
#endif
default: break ;
}
}

View File

@ -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() ) {

View File

@ -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,17 +161,11 @@ 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(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;
@ -336,15 +304,12 @@ void uselessinquiry()
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();
@ -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");
}
@ -501,18 +465,16 @@ 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;
if (slot < 2) {
sd_file *handle;
sprintf (path, "dev%d:\\%s\\%s\\%08x.fcs", ChosenSlot, FCEUDIR, SAVEDIR, iNESGameCRC32);
int offset = 0;
FILE *handle;
if (mode == 0) ShowAction ("Saving STATE to SD...");
else ShowAction ("Loading STATE from SD...");
handle = SDCARD_OpenFile(path, (mode == 0) ? "wb" : "rb");
sprintf (path, "/%s/%s/%08x.fcs", FCEUDIR, SAVEDIR, iNESGameCRC32);
handle = fopen(path, (mode == 0) ? "wb" : "rb");
if (handle == NULL) {
sprintf(msg, "Couldn't open %s", path);
@ -523,8 +485,8 @@ void SD_ManageState(int mode, int slot) {
if (mode == 0) { //Save
filesize = GCFCEUSS_Save();
len = SDCARD_WriteFile (handle, statebuffer, filesize);
SDCARD_CloseFile (handle);
len = fwrite(statebuffer, filesize, 1, handle);
fclose(handle);
if (len != filesize){
sprintf (msg, "Error writing %s", path);
@ -534,12 +496,11 @@ void SD_ManageState(int mode, int slot) {
sprintf (msg, "Saved %d bytes successfully", filesize);
WaitPrompt (msg);
}
else{ //Load
} else { //Load
memopen();
while ((len = SDCARD_ReadFile (handle, &statebuffer[offset], 1024)) > 0) offset += len;
SDCARD_CloseFile (handle);
while ((len = fread(&statebuffer[offset], 1, 1024, handle)) > 0)
offset += len;
fclose(handle);
sprintf (msg, "Loaded %d bytes successfully", offset);
ShowAction(msg);
@ -547,116 +508,6 @@ void SD_ManageState(int mode, int slot) {
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);
}
if (res != FR_OK) {
sprintf(msg, "Failed to open %s, error %d.", path, res);
WaitPrompt(msg);
return;
}
if (mode == 0) { // Save
u32 written = 0, total_written = 0;
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
}
}
void ManageState(int mode, int slot, int device) {
@ -884,16 +735,12 @@ 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...");
handle = SDCARD_OpenFile(path, (mode == 0) ? "wb" : "rb");
if (handle == NULL) {
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);
@ -902,23 +749,15 @@ void SD_ManageSettings(int mode, int slot, int quiet) {
if (mode == 0) { // Save
filesize = SaveSettings(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;
}
len = fwrite(buffer, filesize, 1, f);
fclose(f);
sprintf(msg, "Saved settings successfully");
if (quiet) ShowAction(msg);
else WaitPrompt(msg);
} else { // Load
len = SDCARD_ReadFile(handle, buffer, 128);
SDCARD_CloseFile (handle);
fread(buffer, 128, 1, f);
fclose(f);
/*** Finally, do load ***/
filesize = LoadSettings(buffer);
@ -927,83 +766,6 @@ void SD_ManageSettings(int mode, int slot, int quiet) {
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
}
}
void ManageSettings(int mode, int slot, int device, int quiet) {

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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 */

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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