140
Makefile
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
#---------------------------------------------------------------------------------
|
||||
# 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 := $(notdir $(CURDIR))
|
||||
TARGET := gcmm_WII
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
DATA := data
|
||||
INCLUDES :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE)
|
||||
CXXFLAGS = $(CFLAGS)
|
||||
|
||||
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -lwiiuse -lbte -lfat -logc -lm -lfreetype
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
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
|
||||
#---------------------------------------------------------------------------------
|
||||
140
Makefile.gc
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
#---------------------------------------------------------------------------------
|
||||
# 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)/gamecube_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 := $(notdir $(CURDIR))
|
||||
TARGET := gcmm_GC
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
DATA := data
|
||||
INCLUDES :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE)
|
||||
CXXFLAGS = $(CFLAGS)
|
||||
|
||||
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -lfat -logc -lm -lfreetype
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
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
|
||||
#---------------------------------------------------------------------------------
|
||||
BIN
background/Buttons/16px-GCNXButton.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
background/Buttons/24px-Button-.svg.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
background/Buttons/24px-Buttonhome.svg.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
background/Buttons/24px-Buttonplus.svg.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
background/Buttons/24px-GCNAButton.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
background/Buttons/24px-GCNBButton.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
background/Buttons/24px-GCNStartButton.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
background/Buttons/24px-GCNYButton.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
background/Buttons/24px-WiimoteButton1.svg.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
background/Buttons/24px-WiimoteButton2.svg.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
background/Buttons/24px-Wiimote_B_button.svg.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
background/Buttons/26px-ButtonA.svg.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
background/Buttons/26px-GCNLButton.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
background/Buttons/26px-GCNRButton.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
background/Buttons/28px-GCNZButton.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
background/Buttons/30px-D-Pad_Main-arn.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
background/Buttons/30px-GCControlStickC.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
background/Buttons/30px-GC_D-Pad.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
background/Buttons/30px-GameCubeControlStick.svg.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
background/Buttons/43px-GCNController.svg.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
background/Buttons/8px-Wiimote1.svg.png
Normal file
|
After Width: | Height: | Size: 977 B |
BIN
background/wiibk.psd
Normal file
170
source/bitmap.c
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
/****************************************************************************
|
||||
* bitmap.c
|
||||
*
|
||||
* libogc example to display a Windows bitmap.
|
||||
*
|
||||
* NOTE: Windows BMP must comply to the following:
|
||||
* 24-bit uncompressed (99.99% of Windows Editor output)
|
||||
* Be less than or equal to 640 x 480(MPAL/NTSC) 640x528(PAL)
|
||||
*
|
||||
* This example decodes a BMP file onto the linear framebuffer.
|
||||
****************************************************************************/
|
||||
#include <gccore.h>
|
||||
#include <ogcsys.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "bitmap.h"
|
||||
|
||||
//*extern GXRModeObj *vmode; /*** Graphics Mode Object ***/
|
||||
//extern u32 *xfb[2] = { NULL, NULL }; /*** Framebuffers ***/
|
||||
//extern int whichfb = 0; /*** Frame buffer toggle ***/
|
||||
|
||||
/****************************************************************************
|
||||
* Supporting Functions
|
||||
*
|
||||
* Intel to PowerPC
|
||||
* FLIP32 Convert little to big endian ints.
|
||||
* FLIP16 Convert little to big endian shorts.
|
||||
* CvtRGB Convert RGB pixels to Y1CbY2Cr.
|
||||
****************************************************************************/
|
||||
u32 FLIP32(u32 value) {
|
||||
u32 b;
|
||||
|
||||
b = (value & 0xff) << 24;
|
||||
b |= (value & 0xff00) << 8;
|
||||
b |= (value & 0xff0000) >> 8;
|
||||
b |= (value & 0xff000000) >> 24;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
u16 FLIP16(u16 value) {
|
||||
return ((value & 0xff) << 8) | ((value & 0xff00) >> 8);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* CvtRGB
|
||||
*
|
||||
* This function simply returns two RGB pixels as one Y1CbY2Cr.
|
||||
*****************************************************************************/
|
||||
u32 CvtRGB(u8 r1, u8 g1, u8 b1, u8 r2, u8 g2, u8 b2) {
|
||||
int y1, cb1, cr1, y2, cb2, cr2, cb, cr;
|
||||
|
||||
y1 = (299 * r1 + 587 * g1 + 114 * b1) / 1000;
|
||||
cb1 = (-16874 * r1 - 33126 * g1 + 50000 * b1 + 12800000) / 100000;
|
||||
cr1 = (50000 * r1 - 41869 * g1 - 8131 * b1 + 12800000) / 100000;
|
||||
|
||||
y2 = (299 * r2 + 587 * g2 + 114 * b2) / 1000;
|
||||
cb2 = (-16874 * r2 - 33126 * g2 + 50000 * b2 + 12800000) / 100000;
|
||||
cr2 = (50000 * r2 - 41869 * g2 - 8131 * b2 + 12800000) / 100000;
|
||||
|
||||
cb = (cb1 + cb2) >> 1;
|
||||
cr = (cr1 + cr2) >> 1;
|
||||
|
||||
return (y1 << 24) | (cb << 16)| (y2 << 8)| cr;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Windows 24-Bit Bitmap Header
|
||||
*
|
||||
* These are only the values which are important for GC.
|
||||
****************************************************************************/
|
||||
typedef struct {
|
||||
u16 bfMagic; /*** Always BM ***/
|
||||
u32 bfSize; /*** Size of file ***/
|
||||
u32 bfReserved; /*** Always 0 ***/
|
||||
u32 bfOffset; /*** Offset to pixel data ***/
|
||||
u32 biImageHdrSize; /*** Size of Image info header ***/
|
||||
u32 biWidth; /*** Width of bitmap ***/
|
||||
u32 biHeight; /*** Height of bitmap ***/
|
||||
u16 biPlanes; /*** Number of planes ***/
|
||||
u16 biBitsPerPixel; /*** Bits per pixel ***/
|
||||
u32 biCompression; /*** Is this compressed? ***/
|
||||
} __attribute__ ((__packed__)) WINBITMAP;
|
||||
|
||||
/****************************************************************************
|
||||
* ShowBMP
|
||||
*
|
||||
* This function does some basic checks on the bitmap, to make sure it's the
|
||||
* format expected.
|
||||
*
|
||||
* It will display the bitmap data centred on the NEXT framebuffer.
|
||||
****************************************************************************/
|
||||
u32 ShowBMP(u8 * bmpfile) {
|
||||
WINBITMAP *bitmap;
|
||||
u32 fbwidth, width, height;
|
||||
u8 *bgr;
|
||||
u32 fboffset;
|
||||
u32 rows, cols;
|
||||
|
||||
bitmap = (WINBITMAP *) bmpfile;
|
||||
|
||||
/*** First check, is this a windows bitmap ? ***/
|
||||
if (memcmp (&bitmap->bfMagic, "BM", 2))
|
||||
return 0;
|
||||
|
||||
/*** Only support single plane ***/
|
||||
if (FLIP16 (bitmap->biPlanes) != 1)
|
||||
return 0;
|
||||
|
||||
/*** Only support non-compressed ***/
|
||||
if (FLIP32 (bitmap->biCompression) != 0)
|
||||
return 0;
|
||||
|
||||
/*** 24 bits per pixel ***/
|
||||
if (FLIP16 (bitmap->biBitsPerPixel) != 24)
|
||||
return 0;
|
||||
|
||||
width = FLIP32 (bitmap->biWidth);
|
||||
height = FLIP32 (bitmap->biHeight);
|
||||
|
||||
/*** Will the bitmap fit in the framebuffer? ***/
|
||||
if ((width > 640) || (height > vmode->xfbHeight))
|
||||
return 0;
|
||||
|
||||
/*** Looks like decoding this is ok ***/
|
||||
bgr = (u8 *) bmpfile + FLIP32 (bitmap->bfOffset);
|
||||
|
||||
fbwidth = width;
|
||||
if (fbwidth & 1)
|
||||
fbwidth++;
|
||||
|
||||
/***
|
||||
* Windows BMP files are stored left-to-right, bottom-to-top
|
||||
***/
|
||||
|
||||
/*** Centre width ***/
|
||||
fboffset = ((640 - fbwidth) >> 1) >> 1;
|
||||
|
||||
/*** Centre height ***/
|
||||
fboffset += (((vmode->xfbHeight - height) >> 1) * 320);
|
||||
fboffset += (height * 320);
|
||||
|
||||
/*** Move to NEXT framebuffer ***/
|
||||
whichfb ^= 1;
|
||||
|
||||
for (rows = 0; rows < height; rows++) {
|
||||
for (cols = 0; cols < (fbwidth >> 1); cols++) {
|
||||
xfb[whichfb][fboffset + cols] =CvtRGB (bgr[2], bgr[1], bgr[0],
|
||||
bgr[5], bgr[4], bgr[3]);
|
||||
bgr += 6;
|
||||
}
|
||||
|
||||
fboffset -= 320; /*** Go up one row ***/
|
||||
|
||||
} /*** Outer row loop ***/
|
||||
|
||||
/*** Setup the video to display this picture ***/
|
||||
/*VIDEO_SetNextFramebuffer (xfb[whichfb]);
|
||||
VIDEO_Flush ();
|
||||
VIDEO_WaitVSync ();*/
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ClearScreen() {
|
||||
ShowBMP(bitmapfile);
|
||||
}
|
||||
7
source/bitmap.h
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
/*** 2D Video Globals ***/
|
||||
extern GXRModeObj *vmode; /*** Graphics Mode Object ***/
|
||||
extern u32 *xfb[2]; /*** Framebuffers ***/
|
||||
extern int whichfb; /*** Frame buffer toggle ***/
|
||||
extern u8 bitmapfile[];
|
||||
u32 ShowBMP (u8 *bmpfile);
|
||||
void ClearScreen();
|
||||
12
source/fontface.s
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# Fonts
|
||||
|
||||
.rodata
|
||||
.globl fontface
|
||||
.balign 32
|
||||
fontface:
|
||||
.incbin "../source/ttf/font.ttf"
|
||||
|
||||
|
||||
.globl fontsize
|
||||
fontsize: .long 28736
|
||||
|
||||
770
source/freetype.c
Normal file
|
|
@ -0,0 +1,770 @@
|
|||
/****************************************************************************
|
||||
* libFreeType
|
||||
*
|
||||
* Needed to show the user what's the hell's going on !!
|
||||
* These functions are generic, and do not contain any Memory Card specific
|
||||
* routines.
|
||||
****************************************************************************/
|
||||
#include <gccore.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include "freetype.h"
|
||||
#include "gci.h"
|
||||
#include "mcard.h"
|
||||
#include "sdsupp.h"
|
||||
#include "bitmap.h"
|
||||
#define MCDATAOFFSET 64
|
||||
|
||||
#ifdef HW_RVL
|
||||
#include <wiiuse/wpad.h>
|
||||
#endif
|
||||
|
||||
/*** Globals ***/
|
||||
FT_Library ftlibrary;
|
||||
FT_Face face;
|
||||
FT_GlyphSlot slot;
|
||||
FT_UInt glyph_index;
|
||||
extern int cancel;
|
||||
extern int mode;
|
||||
|
||||
static int fonthi, fontlo;
|
||||
|
||||
/*** The actual TrueType Font ***/
|
||||
extern char fontface[]; /*** From fontface.s ***/
|
||||
extern int fontsize; /*** From fontface.s ***/
|
||||
|
||||
/*** From video subsystem ***/
|
||||
extern int screenheight;
|
||||
extern u32 *xfb[2];
|
||||
extern int whichfb;
|
||||
extern GXRModeObj *vmode;
|
||||
|
||||
/*** File listings ***/
|
||||
extern card_dir CardList[];
|
||||
extern u8 filelist[1024][1024];
|
||||
extern u32 maxfile;
|
||||
extern GCI gci;
|
||||
#define MAXFILEBUFFER (1024 * 2048)
|
||||
extern u8 FileBuffer[MAXFILEBUFFER] ATTRIBUTE_ALIGN (32);
|
||||
#define PAGESIZE 18
|
||||
|
||||
|
||||
#ifdef HW_RVL
|
||||
// POWER BUTTON
|
||||
bool power=false;
|
||||
|
||||
void PowerOff()
|
||||
{
|
||||
//LWP_MutexDestroy(m_audioMutex);
|
||||
SYS_ResetSystem(SYS_POWEROFF, 0, 0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void set_power_var()
|
||||
{
|
||||
power = true;
|
||||
}
|
||||
static void set_wiimote_power_var(s32 chan)
|
||||
{
|
||||
power = true;
|
||||
}
|
||||
void initialise_power()
|
||||
{
|
||||
SYS_SetPowerCallback(set_power_var);
|
||||
WPAD_SetPowerButtonCallback(set_wiimote_power_var);
|
||||
}
|
||||
// END POWER BUTTON
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* FT_Init
|
||||
*
|
||||
* Initialise freetype library
|
||||
****************************************************************************/
|
||||
int FT_Init (){
|
||||
|
||||
int err;
|
||||
|
||||
err = FT_Init_FreeType (&ftlibrary);
|
||||
if (err)
|
||||
return 1;
|
||||
|
||||
err =
|
||||
FT_New_Memory_Face (ftlibrary, (FT_Byte *) fontface, fontsize, 0, &face);
|
||||
if (err)
|
||||
return 1;
|
||||
|
||||
setfontsize (16);
|
||||
setfontcolour (0xff, 0xff, 0xff);
|
||||
|
||||
slot = face->glyph;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* setfontsize
|
||||
****************************************************************************/
|
||||
void setfontsize (int pixelsize){
|
||||
int err;
|
||||
|
||||
err = FT_Set_Pixel_Sizes (face, 0, pixelsize);
|
||||
|
||||
if (err)
|
||||
printf ("Error setting pixel sizes!");
|
||||
}
|
||||
|
||||
static void DrawCharacter (FT_Bitmap * bmp, FT_Int x, FT_Int y){
|
||||
FT_Int i, j, p, q;
|
||||
FT_Int x_max = x + bmp->width;
|
||||
FT_Int y_max = y + bmp->rows;
|
||||
int spos;
|
||||
unsigned int pixel;
|
||||
int c;
|
||||
|
||||
for (i = x, p = 0; i < x_max; i++, p++)
|
||||
{
|
||||
for (j = y, q = 0; j < y_max; j++, q++)
|
||||
{
|
||||
if (i < 0 || j < 0 || i >= 640 || j >= screenheight)
|
||||
continue;
|
||||
|
||||
/*** Convert pixel position to GC int sizes ***/
|
||||
spos = (j * 320) + (i >> 1);
|
||||
|
||||
pixel = xfb[whichfb][spos];
|
||||
c = bmp->buffer[q * bmp->width + p];
|
||||
|
||||
/*** Cool Anti-Aliasing doesn't work too well at hires on GC ***/
|
||||
if (c > 128)
|
||||
{
|
||||
if (i & 1)
|
||||
pixel = (pixel & 0xffff0000) | fontlo;
|
||||
else
|
||||
pixel = ((pixel & 0xffff) | fonthi);
|
||||
|
||||
xfb[whichfb][spos] = pixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DrawText
|
||||
*
|
||||
* Place the font bitmap on the screen
|
||||
*/
|
||||
void DrawText (int x, int y, char *text){
|
||||
int px, n;
|
||||
int i;
|
||||
int err;
|
||||
int value, count;
|
||||
|
||||
n = strlen (text);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
/*** x == -1, auto centre ***/
|
||||
if (x == -1)
|
||||
{
|
||||
value = 0;
|
||||
px = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = 1;
|
||||
px = x;
|
||||
}
|
||||
|
||||
for (count = value; count < 2; count++)
|
||||
{
|
||||
/*** Draw the string ***/
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
err = FT_Load_Char (face, text[i], FT_LOAD_RENDER);
|
||||
|
||||
if (err)
|
||||
{
|
||||
printf ("Error %c %d\n", text[i], err);
|
||||
continue; /*** Skip unprintable characters ***/
|
||||
}
|
||||
|
||||
if (count)
|
||||
DrawCharacter (&slot->bitmap, px + slot->bitmap_left,
|
||||
y - slot->bitmap_top);
|
||||
|
||||
px += slot->advance.x >> 6;
|
||||
}
|
||||
|
||||
px = (640 - px) >> 1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* getcolour
|
||||
*
|
||||
* Simply converts RGB to Y1CbY2Cr format
|
||||
*
|
||||
* I got this from a pastebin, so thanks to whoever originally wrote it!
|
||||
*/
|
||||
|
||||
static unsigned int getcolour (u8 r1, u8 g1, u8 b1){
|
||||
int y1, cb1, cr1, y2, cb2, cr2, cb, cr;
|
||||
u8 r2, g2, b2;
|
||||
|
||||
r2 = r1;
|
||||
g2 = g1;
|
||||
b2 = b1;
|
||||
|
||||
y1 = (299 * r1 + 587 * g1 + 114 * b1) / 1000;
|
||||
cb1 = (-16874 * r1 - 33126 * g1 + 50000 * b1 + 12800000) / 100000;
|
||||
cr1 = (50000 * r1 - 41869 * g1 - 8131 * b1 + 12800000) / 100000;
|
||||
|
||||
y2 = (299 * r2 + 587 * g2 + 114 * b2) / 1000;
|
||||
cb2 = (-16874 * r2 - 33126 * g2 + 50000 * b2 + 12800000) / 100000;
|
||||
cr2 = (50000 * r2 - 41869 * g2 - 8131 * b2 + 12800000) / 100000;
|
||||
|
||||
cb = (cb1 + cb2) >> 1;
|
||||
cr = (cr1 + cr2) >> 1;
|
||||
|
||||
return ((y1 << 24) | (cb << 16) | (y2 << 8) | cr);
|
||||
}
|
||||
|
||||
/**
|
||||
* setfontcolour
|
||||
*
|
||||
* Uses RGB triple values.
|
||||
*/
|
||||
void setfontcolour (u8 r, u8 g, u8 b){
|
||||
u32 fontcolour;
|
||||
|
||||
fontcolour = getcolour (r, g, b);
|
||||
fonthi = fontcolour & 0xffff0000;
|
||||
fontlo = fontcolour & 0xffff;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* ClearScreen
|
||||
****************************************************************************/
|
||||
/*void ClearScreen (){
|
||||
whichfb ^= 1;
|
||||
VIDEO_ClearFrameBuffer (vmode, xfb[whichfb], COLOR_BLACK);
|
||||
}
|
||||
*/
|
||||
/****************************************************************************
|
||||
* ShowScreen
|
||||
****************************************************************************/
|
||||
void ShowScreen (){
|
||||
VIDEO_SetNextFramebuffer (xfb[whichfb]);
|
||||
VIDEO_Flush ();
|
||||
VIDEO_WaitVSync ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show an action in progress
|
||||
*/
|
||||
void ShowAction (char *msg){
|
||||
//int ypos = screenheight >> 1;
|
||||
//ypos += 16;
|
||||
|
||||
//ClearScreen ();
|
||||
//DrawText (-1, ypos, msg);
|
||||
writeStatusBar(msg,"");
|
||||
ShowScreen ();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* SelectMode
|
||||
****************************************************************************/
|
||||
int SelectMode (){
|
||||
/*
|
||||
int ypos;
|
||||
|
||||
ypos = (screenheight >> 1);
|
||||
|
||||
ClearScreen ();
|
||||
DrawText (-1, ypos, "Press A for SMB BACKUP mode");
|
||||
DrawText (-1, ypos + 20, "Press B for SMB RESTORE mode");
|
||||
DrawText (-1, ypos + 40, "Press Y for SD CARD BACKUP mode");
|
||||
DrawText (-1, ypos + 60, "Press X for SD CARD RESTORE mode");
|
||||
DrawText (-1, ypos + 80, "Press Z for SD/PSO Reload");
|
||||
ShowScreen ();*/
|
||||
ClearScreen ();
|
||||
//setfontcolour(84,174,211);
|
||||
// setfontcolour(28,28,28);
|
||||
|
||||
// DrawText(495,305,"choose your mode");
|
||||
writeStatusBar("Choose your mode","");
|
||||
ShowScreen();
|
||||
/*** Clear any pending buttons - button 'debounce' ***/
|
||||
while (PAD_ButtonsHeld (0)
|
||||
#ifdef HW_RVL
|
||||
| WPAD_ButtonsHeld(0)
|
||||
#endif
|
||||
)
|
||||
VIDEO_WaitVSync ();
|
||||
|
||||
for (;;){
|
||||
|
||||
if (PAD_ButtonsHeld (0) & PAD_BUTTON_A){
|
||||
while ((PAD_ButtonsDown (0) & PAD_BUTTON_A)){ VIDEO_WaitVSync (); }
|
||||
return 100;
|
||||
}
|
||||
if (PAD_ButtonsHeld (0) & PAD_TRIGGER_Z){
|
||||
while ((PAD_ButtonsDown (0) & PAD_BUTTON_B)){ VIDEO_WaitVSync (); }
|
||||
return 200;
|
||||
}
|
||||
if (PAD_ButtonsHeld (0) & PAD_BUTTON_Y){
|
||||
while ((PAD_ButtonsDown (0) & PAD_BUTTON_Y)){ VIDEO_WaitVSync (); }
|
||||
return 300;
|
||||
}
|
||||
if (PAD_ButtonsHeld (0) & PAD_BUTTON_X){
|
||||
while ((PAD_ButtonsDown (0) & PAD_BUTTON_X)){ VIDEO_WaitVSync (); }
|
||||
return 400;
|
||||
}
|
||||
if (PAD_ButtonsHeld (0) & PAD_BUTTON_START){
|
||||
while ((PAD_ButtonsDown (0) & PAD_BUTTON_START)){ VIDEO_WaitVSync (); }
|
||||
return 500;
|
||||
}
|
||||
|
||||
#ifdef HW_RVL
|
||||
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_A){
|
||||
while ((WPAD_ButtonsDown (0) & WPAD_BUTTON_A)){ VIDEO_WaitVSync (); }
|
||||
return 100;
|
||||
}
|
||||
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_2){
|
||||
while ((WPAD_ButtonsDown (0) & WPAD_BUTTON_MINUS)){ VIDEO_WaitVSync (); }
|
||||
return 200;
|
||||
}
|
||||
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_MINUS){
|
||||
while ((WPAD_ButtonsDown (0) & WPAD_BUTTON_MINUS)){ VIDEO_WaitVSync (); }
|
||||
return 300;
|
||||
}
|
||||
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_PLUS){
|
||||
while ((WPAD_ButtonsDown (0) & WPAD_BUTTON_PLUS)){ VIDEO_WaitVSync (); }
|
||||
return 400;
|
||||
}
|
||||
if (WPAD_ButtonsHeld (0) & WPAD_BUTTON_HOME){
|
||||
while ((WPAD_ButtonsDown (0) & WPAD_BUTTON_HOME)){ VIDEO_WaitVSync (); }
|
||||
return 500;
|
||||
}
|
||||
if (power){
|
||||
PowerOff();
|
||||
}
|
||||
#endif
|
||||
|
||||
VIDEO_WaitVSync ();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for user to press A
|
||||
*/
|
||||
void WaitButtonA (){
|
||||
#ifdef HW_DOL
|
||||
while (PAD_ButtonsDown (0) & PAD_BUTTON_A );
|
||||
while (!(PAD_ButtonsDown (0) & PAD_BUTTON_A));
|
||||
#else
|
||||
while (1){
|
||||
if (PAD_ButtonsDown (0) & PAD_BUTTON_A )
|
||||
break;
|
||||
if (WPAD_ButtonsDown (0) & WPAD_BUTTON_A )
|
||||
break;
|
||||
if (power){
|
||||
PowerOff();
|
||||
}
|
||||
}
|
||||
while (1){
|
||||
if (!(PAD_ButtonsDown (0) & PAD_BUTTON_A))
|
||||
break;
|
||||
if (!(WPAD_ButtonsDown (0) & WPAD_BUTTON_A))
|
||||
break;
|
||||
if (power){
|
||||
PowerOff();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a prompt
|
||||
*/
|
||||
void WaitPrompt (char *msg){
|
||||
//int ypos = (screenheight) >> 1;
|
||||
//ClearScreen ();
|
||||
//DrawText (-1, ypos, msg);
|
||||
//ypos += 20;
|
||||
//DrawText (-1, ypos, "Press A to continue");
|
||||
writeStatusBar(msg,"Press A to continue");
|
||||
ShowScreen ();
|
||||
WaitButtonA ();
|
||||
//clear the text
|
||||
int bgcolor = getcolour(0xff,0xff,0xff);
|
||||
DrawBoxFilled(10, 430, 510, 485, bgcolor);
|
||||
}
|
||||
|
||||
void DrawLineFast (int startx, int endx, int y, u8 r, u8 g, u8 b){
|
||||
int width;
|
||||
u32 offset;
|
||||
u32 colour;
|
||||
int i;
|
||||
|
||||
offset = (y * 320) + (startx >> 1);
|
||||
colour = getcolour (r, g, b);
|
||||
width = (endx - startx) >> 1;
|
||||
|
||||
for (i = 0; i < width; i++)
|
||||
xfb[whichfb][offset++] = colour;
|
||||
}
|
||||
|
||||
void showSaveInfo(int sel) {
|
||||
int y = 190, x = 380, j;
|
||||
char gamecode[5], company[3], txt[1024];
|
||||
|
||||
//clear right pane, but we don't want to erase previous text
|
||||
int bgcolor = getcolour(84,174,211);
|
||||
DrawBoxFilled(375, 175, 605, 410, bgcolor);
|
||||
|
||||
// memcpy(company, CardList[sel].company, 2);
|
||||
// memcpy(gamecode, CardList[sel].gamecode, 4);
|
||||
//company[2] = gamecode[4] = 0;
|
||||
|
||||
// read file, display some more info
|
||||
// TODO: only read the necessary header + comment for sd
|
||||
if (mode == RESTORE_MODE){
|
||||
j = SDLoadMCImageHeader(filelist[sel]);
|
||||
memcpy(&gci, FileBuffer, 64);
|
||||
ExtractGCIHeader();
|
||||
GCIMakeHeader();
|
||||
|
||||
}else if( mode == RESTORE_MODE || mode == DELETE_MODE){
|
||||
j = CardReadFileHeader(CARD_SLOTB, sel);
|
||||
}
|
||||
// struct gci now contains header info
|
||||
|
||||
memcpy(company, gci.company, 2);
|
||||
memcpy(gamecode, gci.gamecode, 4);
|
||||
company[2] = gamecode[4] = 0;
|
||||
sprintf(txt, "#%d %s/%s", sel, gamecode, company);
|
||||
DrawText(x, y, txt);
|
||||
y += 20;
|
||||
|
||||
// Compute date/time
|
||||
u32 t = gci.time; // seconds since jan 1, 2000
|
||||
int month, day, year, hour, min, sec;
|
||||
month = day = year = hour = min = sec = 0;
|
||||
sprintf(txt, "D: %08lX", t);
|
||||
DrawText(x, y, txt);
|
||||
y += 20;
|
||||
|
||||
int monthdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
char monthstr[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
|
||||
"Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||
sec = t % 60;
|
||||
t /= 60;
|
||||
min = t % 60;
|
||||
t /= 60;
|
||||
hour = t % 24;
|
||||
t /= 24;
|
||||
day = t % 365;
|
||||
year = t / 365;
|
||||
// figure in leap years
|
||||
day -= year / 4;
|
||||
if ( (year % 4 == 0) && (day > 31+29) ) {
|
||||
// TODO: check if day<0, go back one month
|
||||
day--;
|
||||
}
|
||||
// day now is number of days into the year
|
||||
for(j=0; j<12; j++) {
|
||||
if (day > monthdays[j]) {
|
||||
month++;
|
||||
day -= monthdays[j];
|
||||
} else {
|
||||
j = 12;
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(txt, "Date: %s %02d, %04d", monthstr[month], day+1, year+2000);
|
||||
DrawText(x, y, txt);
|
||||
y += 20;
|
||||
sprintf(txt, "Time: %02d:%02d:%02d", hour, min, sec);
|
||||
DrawText(x, y, txt);
|
||||
y += 20;
|
||||
sprintf(txt, "Blocks: %d", gci.filesize8);
|
||||
DrawText(x, y, txt);
|
||||
y += 20;
|
||||
sprintf(txt, "Perm: %s%s%s",
|
||||
(gci.unknown1 & 16) ? "M " : "x",
|
||||
(gci.unknown1 & 8) ? "C " : "x",
|
||||
(gci.unknown1 & 4) ? "P" : "x");
|
||||
DrawText(x, y, txt);
|
||||
y += 20;
|
||||
// Comment at MCDATAOFFSET+(comment addr)
|
||||
char *comment = (char*) (FileBuffer+MCDATAOFFSET+gci.comment_addr);
|
||||
j = 0;
|
||||
int x2, z = 0;
|
||||
int offset = 0;
|
||||
for (x2=t=0; (t<strlen(comment)) && (t<64); t++) {
|
||||
z++;
|
||||
//x2 += font_size[(int)comment[t]];
|
||||
x2 += 16;
|
||||
if (x2 > 225) { // max width of left pane
|
||||
strncpy(txt, comment+offset, z-1);
|
||||
txt[z-1] = 0;
|
||||
//char c = txt[t];
|
||||
//txt[t] = 0;
|
||||
DrawText(x, y, txt);
|
||||
y += 20;
|
||||
offset = t-1;
|
||||
//txt[t] = c;
|
||||
//strcpy(txt, comment+t);
|
||||
z = 0;
|
||||
//x2 = font_size[(int)comment[t]];
|
||||
x2 = 16;
|
||||
}
|
||||
}
|
||||
|
||||
if (z) {
|
||||
strcpy(txt, comment+offset);
|
||||
//txt[z] = 0;
|
||||
DrawText(x, y, txt);
|
||||
y += 20;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void ShowFiles (int offset, int selection){
|
||||
int i, j;
|
||||
char text[80];
|
||||
int ypos;
|
||||
int w;
|
||||
|
||||
clearLeftPane();
|
||||
|
||||
//setfontsize (16);
|
||||
setfontsize (14);
|
||||
//ypos = 70;
|
||||
ypos = (screenheight - (PAGESIZE * 20)) >> 1;
|
||||
//ypos += 20;
|
||||
ypos += 25;
|
||||
j = 0;
|
||||
for (i = offset; i < (offset + PAGESIZE) && (i < maxfile); i++){
|
||||
strcpy (text, filelist[i]);
|
||||
if (j == (selection - offset)){
|
||||
/*** Highlighted text entry ***/
|
||||
for (w = 0; w < 20; w++){
|
||||
// DrawLineFast (30, 610, (j * 20) + (ypos - 16) + w, 0x00, 0x00, 0xC0);
|
||||
//DrawLineFast (35, 330, (j * 20) + (ypos - 16) + w, 0xff, 0xff, 0xff);
|
||||
DrawLineFast (35, 330, (j * 20) + (ypos - 14) + w, 0xff, 0xff, 0xff);
|
||||
|
||||
}
|
||||
//setfontcolour (0xff, 0xff, 0xff);
|
||||
//setfontcolour (84, 174, 211);
|
||||
setfontcolour (28, 28, 28);
|
||||
// DrawText (-1, (j * 20) + ypos, text);
|
||||
DrawText (35, (j * 20) + ypos, text);
|
||||
|
||||
showSaveInfo(selection);
|
||||
|
||||
setfontcolour (0xff, 0xff, 0xff);
|
||||
|
||||
//setfontcolour (0xc0, 0xc0, 0xc0);
|
||||
}
|
||||
else{
|
||||
/*** Normal entry ***/
|
||||
//****************
|
||||
for (w = 0; w < 20; w++){
|
||||
// DrawLineFast (30, 610, (j * 20) + (ypos - 16) + w, 0x00, 0x00, 0xC0);
|
||||
|
||||
//DrawLineFast (35, 330, (j * 20) + (ypos - 16) + w, 84, 174,211);
|
||||
DrawLineFast (35, 330, (j * 20) + (ypos - 14) + w, 84, 174,211);
|
||||
//***********************************************************
|
||||
}
|
||||
DrawText (35, (j * 20) + ypos, text);
|
||||
}
|
||||
j++;
|
||||
}
|
||||
ShowScreen ();
|
||||
}
|
||||
|
||||
/*void ShowFiles(int offset, int selected, int maxfiles) {
|
||||
int y = 110, tmp;
|
||||
|
||||
//WaitPrompt("ShowFiles");
|
||||
clearLeftPane();
|
||||
for (tmp = offset; (tmp<offset+PAGESIZE) && (tmp < maxfiles); tmp++) {
|
||||
char str[1024], txt[1024];
|
||||
int x, t;
|
||||
strcpy(str, CardList[tmp].filename);
|
||||
for (x=t=0; t<strlen(str); t++) {
|
||||
x += font_size[(int)str[t]];
|
||||
if (x > 290) { // max width of left pane
|
||||
str[t] = 0;
|
||||
t = strlen(str);
|
||||
}
|
||||
}
|
||||
strcpy(txt, str);
|
||||
//txt[t-1] = 0;
|
||||
if (tmp == selected) {
|
||||
// Highlight this file
|
||||
fntDrawBoxFilled(35, y, 330, y+23, hlcolor);
|
||||
showSaveInfo(selected);
|
||||
}
|
||||
write_font(35, y, txt); // write filename on left
|
||||
y += 20;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* ShowSelector
|
||||
*
|
||||
* Let's the user select a file to backup or restore.
|
||||
* Returns index of file chosen.
|
||||
****************************************************************************/
|
||||
int ShowSelector (){
|
||||
u32 p, wp;
|
||||
int redraw = 1;
|
||||
int quit = 0;
|
||||
int offset, selection;
|
||||
|
||||
offset = selection = 0;
|
||||
|
||||
while (quit == 0){
|
||||
if (redraw){
|
||||
ShowFiles (offset, selection);
|
||||
redraw = 0;
|
||||
}
|
||||
p = PAD_ButtonsDown (0);
|
||||
#ifdef HW_RVL
|
||||
wp = WPAD_ButtonsDown (0);
|
||||
#endif
|
||||
if ((p & PAD_BUTTON_B )
|
||||
#ifdef HW_RVL
|
||||
| (wp & WPAD_BUTTON_B)
|
||||
#endif
|
||||
){
|
||||
cancel = 1;
|
||||
return;
|
||||
}
|
||||
#ifdef HW_RVL
|
||||
if (power){
|
||||
PowerOff();
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((p & PAD_BUTTON_A)
|
||||
#ifdef HW_RVL
|
||||
| (wp & WPAD_BUTTON_A)
|
||||
#endif
|
||||
){
|
||||
return selection;
|
||||
}
|
||||
if ((p & PAD_BUTTON_DOWN)
|
||||
#ifdef HW_RVL
|
||||
| (wp & WPAD_BUTTON_DOWN)
|
||||
#endif
|
||||
) {
|
||||
selection++;
|
||||
if (selection == maxfile){
|
||||
selection = offset = 0;
|
||||
}
|
||||
if ((selection - offset) >= PAGESIZE){
|
||||
offset += PAGESIZE;
|
||||
}
|
||||
redraw = 1;
|
||||
}
|
||||
if ((p & PAD_BUTTON_UP)
|
||||
#ifdef HW_RVL
|
||||
| (wp & WPAD_BUTTON_UP)
|
||||
#endif
|
||||
){
|
||||
selection--;
|
||||
if (selection < 0){
|
||||
selection = maxfile - 1;
|
||||
offset = selection - PAGESIZE + 1;
|
||||
}
|
||||
if (selection < offset){
|
||||
offset -= PAGESIZE;
|
||||
}
|
||||
if (offset < 0){
|
||||
offset = 0;
|
||||
}
|
||||
redraw = 1;
|
||||
}
|
||||
}
|
||||
return selection;
|
||||
}
|
||||
|
||||
void writeStatusBar(char *line1, char *line2) {
|
||||
int bgcolor = getcolour(0xff,0xff,0xff);
|
||||
//DrawBoxFilled(10, 404, 510, 455, bgcolor);
|
||||
DrawBoxFilled(10, 430, 510, 485, bgcolor);
|
||||
//setfontcolour(84,174,211);
|
||||
setfontcolour(28,28,28);
|
||||
DrawText(40, 450, line1);
|
||||
DrawText(40, 475, line2);
|
||||
}
|
||||
|
||||
void clearLeftPane() {
|
||||
int bgcolor = getcolour(84,174,211);
|
||||
DrawBoxFilled(34, 110, 333, 380, bgcolor);
|
||||
}
|
||||
|
||||
void clearRightPane() {
|
||||
int bgcolor = getcolour(84,174,211);
|
||||
DrawBoxFilled(375, 140, 605, 410, bgcolor);
|
||||
}
|
||||
|
||||
void DrawHLine (int x1, int x2, int y, int color)
|
||||
{
|
||||
int i;
|
||||
y = 320 * y;
|
||||
x1 >>= 1;
|
||||
x2 >>= 1;
|
||||
for (i = x1; i <= x2; i++) {
|
||||
int *tmpfb = xfb[whichfb];
|
||||
tmpfb[y+i] = color;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawVLine (int x, int y1, int y2, int color)
|
||||
{
|
||||
int i;
|
||||
x >>= 1;
|
||||
for (i = y1; i <= y2; i++) {
|
||||
int *tmpfb = xfb[whichfb];
|
||||
tmpfb[x + (640 * i) / 2] = color;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawBox (int x1, int y1, int x2, int y2, int color)
|
||||
{
|
||||
DrawHLine (x1, x2, y1, color);
|
||||
DrawHLine (x1, x2, y2, color);
|
||||
DrawVLine (x1, y1, y2, color);
|
||||
DrawVLine (x2, y1, y2, color);
|
||||
}
|
||||
|
||||
void DrawBoxFilled (int x1, int y1, int x2, int y2, int color)
|
||||
{
|
||||
int h;
|
||||
for (h = y1; h <= y2; h++)
|
||||
DrawHLine (x1, x2, h, color);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
39
source/freetype.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/****************************************************************************
|
||||
* FreeType font
|
||||
****************************************************************************/
|
||||
#ifndef _FTFONTS_
|
||||
#define _FTFONTS_
|
||||
|
||||
//#define PRESSED_BUTTON_A 100 /* Free mode */
|
||||
#define DELETE_MODE 200
|
||||
#define BACKUP_MODE 300
|
||||
#define RESTORE_MODE 400
|
||||
//#define RELOAD_MODE 500 /* Free mode */
|
||||
|
||||
#ifdef HW_RVL
|
||||
void initialise_power() ;
|
||||
#endif
|
||||
|
||||
int FT_Init ();
|
||||
void setfontsize (int pixelsize);
|
||||
void setfontcolour (u8 r, u8 g, u8 b);
|
||||
void DrawText (int x, int y, char *text);
|
||||
//extern void ClearScreen ();
|
||||
void ShowScreen ();
|
||||
void ShowAction (char *msg);
|
||||
void WaitPrompt (char *msg);
|
||||
int ShowSelector ();
|
||||
int SelectMode ();
|
||||
void writeStatusBar(char *line1, char *line2);
|
||||
void clearLeftPane();
|
||||
void clearRightPane();
|
||||
/****************************************************************************
|
||||
* Draw functions - lines, boxes
|
||||
****************************************************************************/
|
||||
void DrawHLine (int x1, int x2, int y, int color);
|
||||
void DrawVLine (int x, int y1, int y2, int color);
|
||||
void DrawBox (int x1, int y1, int x2, int y2, int color);
|
||||
void DrawBoxFilled (int x1, int y1, int x2, int y2, int color);
|
||||
|
||||
|
||||
#endif
|
||||
BIN
source/gcbk.bmp
Normal file
|
After Width: | Height: | Size: 844 KiB |
31
source/gci.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/****************************************************************************
|
||||
* GCI Memory Card stuff
|
||||
*
|
||||
* This is an attempt at compatibility.
|
||||
****************************************************************************/
|
||||
#ifndef __GCIHDR_
|
||||
#define __GCIHDR_
|
||||
|
||||
#include <gccore.h>
|
||||
|
||||
typedef struct {
|
||||
u8 gamecode[4];
|
||||
u8 company[2];
|
||||
u8 reserved01; /*** Always 0xff ***/
|
||||
u8 banner_fmt;
|
||||
u8 filename[CARD_FILENAMELEN];
|
||||
u32 time;
|
||||
u32 icon_addr;
|
||||
u16 icon_fmt;
|
||||
u16 icon_speed;
|
||||
u8 unknown1; /*** Permission key? ***/
|
||||
u8 unknown2; /*** Again, unknown ***/
|
||||
u16 index; /*** Ignore - and throw away ***/
|
||||
u16 filesize8; /*** File size / 8192 ***/
|
||||
u16 reserved02; /*** Always 0xffff ***/
|
||||
u32 comment_addr;
|
||||
} __attribute__((__packed__)) GCI;
|
||||
|
||||
#define MCDATAOFFSET 64
|
||||
|
||||
#endif
|
||||
6
source/gcmm-bk.gamecube
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
.rodata
|
||||
.globl bitmapfile
|
||||
.balign 32
|
||||
bitmapfile:
|
||||
.incbin "../source/gcbk.bmp"
|
||||
|
||||
6
source/gcmm-bk.s
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
.rodata
|
||||
.globl bitmapfile
|
||||
.balign 32
|
||||
bitmapfile:
|
||||
.incbin "../source/wiibk.bmp"
|
||||
|
||||
353
source/main.c
Normal file
|
|
@ -0,0 +1,353 @@
|
|||
/****************************************************************************
|
||||
* ds bomb gamecube memory card manager
|
||||
*based on libOGC Memory Card Backup by askot
|
||||
* delete support + saves information made by dsbomb
|
||||
* Gui original design by dsbomb
|
||||
* Gui adds and user interaction by justb
|
||||
* Uses freetype.
|
||||
* libFreeType is available from the downloads sections.
|
||||
*****************************************************************************/
|
||||
#include <gccore.h>
|
||||
#include <ogcsys.h>
|
||||
#include <network.h>
|
||||
#include <smb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fat.h>
|
||||
#include <sys/dir.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef HW_RVL
|
||||
#include <wiiuse/wpad.h>
|
||||
#endif
|
||||
|
||||
#include "mcard.h"
|
||||
#include "sdsupp.h"
|
||||
#include "freetype.h"
|
||||
#include "bitmap.h"
|
||||
|
||||
#define PSOSDLOADID 0x7c6000a6
|
||||
int mode;
|
||||
int cancel;
|
||||
/*** 2D Video Globals ***/
|
||||
GXRModeObj *vmode; /*** Graphics Mode Object ***/
|
||||
u32 *xfb[2] = { NULL, NULL }; /*** Framebuffers ***/
|
||||
int whichfb = 0; /*** Frame buffer toggle ***/
|
||||
int screenheight;
|
||||
|
||||
extern u8 filelist[1024][1024];
|
||||
|
||||
static void updatePAD(){
|
||||
PAD_ScanPads();
|
||||
#ifdef HW_RVL
|
||||
WPAD_ScanPads();
|
||||
#endif
|
||||
}
|
||||
static int initFAT(){
|
||||
//init fat filesystem
|
||||
fatInit(8, false);
|
||||
//sleep(2); // espero dos segundos, no se muy bien si para darle tiempo a que el dispositivo negocie o esté preparado para funcionar
|
||||
//fatSetDefaultInterface(PI_INTERNAL_SD); // usa SD como fat:
|
||||
int have_device=0; // bits que me indican la presencia de dispositivos
|
||||
DIR_ITER *dir;
|
||||
char path_initfat[]="fatX:/";
|
||||
#ifdef HW_RVL
|
||||
path_initfat[3]=48+PI_INTERNAL_SD; // path_file ="fatX:/";
|
||||
#else
|
||||
path_initfat[3]=48+PI_SDGECKO_A; // path_file ="fatX:/";
|
||||
#endif
|
||||
|
||||
int n;
|
||||
for(n=0;n<5;n++) // numero de reintentos por si la unidad no está preparada o está "enojada" :lol:
|
||||
{
|
||||
dir = diropen(path_initfat);
|
||||
if (dir) {
|
||||
dirclose(dir);
|
||||
//have_device|=1;
|
||||
have_device=1;
|
||||
#ifdef HW_RVL
|
||||
fatEnableReadAhead(PI_INTERNAL_SD, 12, 32);// monta la cache
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
//usleep(200*1000);
|
||||
}
|
||||
|
||||
return have_device;
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Initialise Video
|
||||
*
|
||||
* Before doing anything in libogc, it's recommended to configure a video
|
||||
* output.
|
||||
****************************************************************************/
|
||||
static void
|
||||
Initialise (void)
|
||||
{
|
||||
VIDEO_Init (); /*** ALWAYS CALL FIRST IN ANY LIBOGC PROJECT!
|
||||
Not only does it initialise the video
|
||||
subsystem, but also sets up the ogc os
|
||||
***/
|
||||
|
||||
PAD_Init (); /*** Initialise pads for input ***/
|
||||
#ifdef HW_RVL
|
||||
WPAD_Init ();
|
||||
#endif
|
||||
|
||||
/*** Try to match the current video display mode
|
||||
using the higher resolution interlaced.
|
||||
|
||||
So NTSC/MPAL gives a display area of 640x480
|
||||
PAL display area is 640x528
|
||||
***/
|
||||
switch (VIDEO_GetCurrentTvMode ())
|
||||
{
|
||||
case VI_NTSC:
|
||||
vmode = &TVNtsc480IntDf;
|
||||
break;
|
||||
|
||||
case VI_PAL:
|
||||
vmode = &TVPal528IntDf;
|
||||
break;
|
||||
|
||||
case VI_MPAL:
|
||||
vmode = &TVMpal480IntDf;
|
||||
break;
|
||||
|
||||
default:
|
||||
vmode = &TVNtsc480IntDf;
|
||||
break;
|
||||
}
|
||||
|
||||
/*** Let libogc configure the mode ***/
|
||||
VIDEO_Configure (vmode);
|
||||
|
||||
/*** Now configure the framebuffer.
|
||||
Really a framebuffer is just a chunk of memory
|
||||
to hold the display line by line.
|
||||
***/
|
||||
|
||||
xfb[0] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer (vmode));
|
||||
/*** I prefer also to have a second buffer for double-buffering.
|
||||
This is not needed for the console demo.
|
||||
***/
|
||||
xfb[1] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer (vmode));
|
||||
|
||||
/*** Define a console ***/
|
||||
console_init (xfb[0], 20, 64, vmode->fbWidth, vmode->xfbHeight,
|
||||
vmode->fbWidth * 2);
|
||||
|
||||
/*** Update screen height for font engine ***/
|
||||
screenheight = vmode->xfbHeight;
|
||||
|
||||
/*** Clear framebuffer to black ***/
|
||||
VIDEO_ClearFrameBuffer (vmode, xfb[0], COLOR_BLACK);
|
||||
VIDEO_ClearFrameBuffer (vmode, xfb[1], COLOR_BLACK);
|
||||
|
||||
/*** Set the framebuffer to be displayed at next VBlank ***/
|
||||
VIDEO_SetNextFramebuffer (xfb[0]);
|
||||
|
||||
/*** Get the PAD status updated by libogc ***/
|
||||
VIDEO_SetPostRetraceCallback (updatePAD);
|
||||
VIDEO_SetBlack (0);
|
||||
|
||||
/*** Update the video for next vblank ***/
|
||||
VIDEO_Flush ();
|
||||
|
||||
VIDEO_WaitVSync (); /*** Wait for VBL ***/
|
||||
if (vmode->viTVMode & VI_NON_INTERLACE)
|
||||
VIDEO_WaitVSync ();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* BackupMode -SD Mode
|
||||
*
|
||||
* Perform backup of a memory card file from a SD Card.
|
||||
****************************************************************************/
|
||||
void SD_BackupMode (){
|
||||
int memitems;
|
||||
int selected = 0;
|
||||
int bytestodo;
|
||||
|
||||
clearRightPane();
|
||||
//DrawText(390,130,"B a c k u p M o d e");
|
||||
DrawText(388,160,"B a c k u p M o d e");
|
||||
writeStatusBar("Pick a file using UP or DOWN ", "Press A to backup to SD Card ") ;
|
||||
/*** Get the directory listing from the memory card ***/
|
||||
memitems = CardGetDirectory (CARD_SLOTB);
|
||||
|
||||
/*** If it's a blank card, get out of here ***/
|
||||
if (!memitems) {WaitPrompt ("No saved games to backup !");}
|
||||
else
|
||||
{
|
||||
selected = ShowSelector ();
|
||||
if (cancel) {WaitPrompt ("Backup action cancelled !");}
|
||||
else
|
||||
{
|
||||
/*** Backup the file ***/
|
||||
ShowAction ("Reading File From MC SLOT B");
|
||||
bytestodo = CardReadFile (CARD_SLOTB, selected);
|
||||
if (bytestodo){
|
||||
ShowAction ("Saving to SD CARD");
|
||||
if (SDSaveMCImage ()){
|
||||
WaitPrompt ("Backup complete");
|
||||
}
|
||||
else{
|
||||
WaitPrompt ("Backup failed");
|
||||
}
|
||||
}
|
||||
else{
|
||||
WaitPrompt ("Error reading MC file");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* RestoreMode
|
||||
*
|
||||
* Restore a file to Memory Card from SD Card
|
||||
****************************************************************************/
|
||||
void SD_RestoreMode (){
|
||||
int files;
|
||||
int selected;
|
||||
|
||||
clearRightPane();
|
||||
//DrawText(390,130,"R e s t o r e M o d e");
|
||||
DrawText(388,160,"R e s t o r e M o d e");
|
||||
writeStatusBar("Pick a file using UP or DOWN", "Press A to restore to Memory Card ") ;
|
||||
files = SDGetFileList ();
|
||||
if (!files) {WaitPrompt ("No saved games in SD Card to restore !");}
|
||||
|
||||
else
|
||||
{
|
||||
selected = ShowSelector ();
|
||||
|
||||
if (cancel) {WaitPrompt ("restore action cancelled !");}
|
||||
else
|
||||
{
|
||||
ShowAction ("Reading from SD Card");
|
||||
if (SDLoadMCImage (filelist[selected])){
|
||||
ShowAction ("Updating Memory Card");
|
||||
if (CardWriteFile (CARD_SLOTB)){
|
||||
WaitPrompt ("Restore Complete");
|
||||
}
|
||||
else {
|
||||
WaitPrompt ("Error during restore");
|
||||
}
|
||||
}
|
||||
else{
|
||||
WaitPrompt ("Error reading image");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* TestMode
|
||||
*
|
||||
*
|
||||
****************************************************************************/
|
||||
/*void testMode (){
|
||||
|
||||
clearRightPane();
|
||||
DrawText(390,130,"T e s t M o d e");
|
||||
|
||||
int bytestodo;
|
||||
|
||||
clearRightPane();
|
||||
|
||||
|
||||
ShowAction ("Reading From MC SLOT B");
|
||||
bytestodo = testreadimage (CARD_SLOTB);
|
||||
if (bytestodo){
|
||||
ShowAction ("Saving to SD CARD");
|
||||
if (SDSaveraw ()){
|
||||
WaitPrompt ("Backup complete");
|
||||
}
|
||||
else{
|
||||
WaitPrompt ("Backup failed");
|
||||
}
|
||||
}
|
||||
else{
|
||||
WaitPrompt ("Error reading MC file");
|
||||
}
|
||||
|
||||
// writeStatusBar("Pick a file using UP or DOWN", "Press A to restore to Memory Card ") ;
|
||||
|
||||
|
||||
//WaitPrompt ("No saved games in SD Card to restore !");
|
||||
//ShowAction ("Reading from SD Card");
|
||||
|
||||
|
||||
}*/
|
||||
|
||||
/****************************************************************************
|
||||
* Main
|
||||
****************************************************************************/
|
||||
int main (){
|
||||
|
||||
|
||||
#ifdef HW_DOL
|
||||
int *psoid = (int *) 0x80001800;
|
||||
void (*PSOReload) () = (void (*)()) 0x80001800;
|
||||
#endif
|
||||
|
||||
Initialise (); /*** Start video ***/
|
||||
FT_Init (); /*** Start FreeType ***/
|
||||
if(!initFAT())
|
||||
WaitPrompt("Insert SDCARD");
|
||||
|
||||
#ifdef HW_RVL
|
||||
initialise_power();
|
||||
#endif
|
||||
|
||||
for (;;){
|
||||
/*** Select Mode ***/
|
||||
ClearScreen();
|
||||
cancel = 0;/******a global value to track action aborted by user pressing button B********/
|
||||
mode = SelectMode ();
|
||||
|
||||
|
||||
/*** Mode == 100 for backup, 200 for restore ***/
|
||||
switch (mode){
|
||||
case 100 :
|
||||
//SMB_BackupMode();
|
||||
//WaitPrompt ("Inactive");
|
||||
break;
|
||||
case 200 :
|
||||
MC_DeleteMode(CARD_SLOTB);
|
||||
break;
|
||||
case 300 :
|
||||
SD_BackupMode();
|
||||
break;
|
||||
case 400 :
|
||||
SD_RestoreMode();
|
||||
break;
|
||||
case 500 :
|
||||
#ifdef HW_RVL
|
||||
if (!!*(u32*)0x80001800) exit(1);
|
||||
else SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
|
||||
#else
|
||||
if (psoid[0] == PSOSDLOADID)
|
||||
PSOReload ();
|
||||
#endif
|
||||
break; //PSO_Reload
|
||||
}
|
||||
}
|
||||
while (1);
|
||||
return 0;
|
||||
}
|
||||
513
source/mcard.c
Normal file
|
|
@ -0,0 +1,513 @@
|
|||
/****************************************************************************
|
||||
* Memory Card
|
||||
*
|
||||
* Supporting functions.
|
||||
*
|
||||
* MAXFILEBUFFER is set to 2MB as it's the largest file I've seen.
|
||||
*
|
||||
* CARDBACKUP FILE
|
||||
*
|
||||
* 0 - Copy of CardDir
|
||||
* 64 - Copy of CardStatus
|
||||
* 192 - Memory Card File Data
|
||||
****************************************************************************/
|
||||
#include <gccore.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "mcard.h"
|
||||
#include "gci.h"
|
||||
#include "freetype.h"
|
||||
|
||||
/*** Memory Card Work Area ***/
|
||||
static u8 SysArea[CARD_WORKAREA] ATTRIBUTE_ALIGN (32);
|
||||
|
||||
/*** Memory File Buffer ***/
|
||||
#define MAXFILEBUFFER (1024 * 2048) /*** 2MB Buffer ***/
|
||||
u8 FileBuffer[MAXFILEBUFFER] ATTRIBUTE_ALIGN (32);
|
||||
u8 filelist[1024][1024];
|
||||
int maxfile;
|
||||
extern int cancel;
|
||||
/*** Card lib ***/
|
||||
card_dir CardList[CARD_MAXFILES]; /*** Directory listing ***/
|
||||
static card_dir CardDir;
|
||||
static card_file CardFile;
|
||||
static card_stat CardStatus;
|
||||
static int cardcount = 0;
|
||||
|
||||
|
||||
GCI gci;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------
|
||||
This function is called if a card is physically removed
|
||||
---------------------------------------------------------------------------------*/
|
||||
void card_removed(s32 chn,s32 result) {
|
||||
//---------------------------------------------------------------------------------
|
||||
printf("card was removed from slot %c\n",(chn==0)?'A':'B');
|
||||
CARD_Unmount(chn);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* MountCard
|
||||
*
|
||||
* Mounts the memory card in the given slot.
|
||||
* Returns the result of the last attempted CARD_Mount command.
|
||||
***************************************************************************/
|
||||
int MountCard(int cslot)
|
||||
{
|
||||
int ret = -1;
|
||||
int tries = 0;
|
||||
|
||||
// Mount the card
|
||||
while ( tries < 10 && ret != 0)
|
||||
{
|
||||
EXI_ProbeReset ();
|
||||
ret = CARD_Mount (cslot, SysArea, card_removed);
|
||||
VIDEO_WaitVSync ();
|
||||
tries++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* GCIMakeHeader
|
||||
*
|
||||
* Create a GCI compatible header from libOGC card_stat
|
||||
****************************************************************************/
|
||||
void GCIMakeHeader()
|
||||
{
|
||||
/*** Clear out the cgi header ***/
|
||||
memset(&gci, 0xff, sizeof(GCI) );
|
||||
|
||||
/*** Populate ***/
|
||||
memcpy(&gci.gamecode, &CardStatus.gamecode, 4);
|
||||
memcpy(&gci.company, &CardStatus.company, 2);
|
||||
gci.banner_fmt = CardStatus.banner_fmt;
|
||||
memcpy(&gci.filename, &CardStatus.filename, CARD_FILENAMELEN);
|
||||
gci.time = CardStatus.time;
|
||||
gci.icon_addr = CardStatus.icon_addr;
|
||||
gci.icon_fmt = CardStatus.icon_fmt;
|
||||
gci.icon_speed = CardStatus.icon_speed;
|
||||
|
||||
/*** In the games I've checked, these are always 0 ***/
|
||||
gci.unknown1 = gci.unknown2 = 0;
|
||||
|
||||
/*** Block index does not matter, it won't be restored at the same spot ***/
|
||||
gci.index = 32;
|
||||
|
||||
gci.filesize8 = (CardStatus.len / 8192);
|
||||
gci.comment_addr = CardStatus.comment_addr;
|
||||
|
||||
/*** Copy to head of buffer ***/
|
||||
memcpy(FileBuffer, &gci, sizeof(GCI));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* ExtractGCIHeader
|
||||
*
|
||||
* Extract a GCI Header to libOGC card_stat
|
||||
****************************************************************************/
|
||||
void ExtractGCIHeader()
|
||||
{
|
||||
/*** Clear out the status ***/
|
||||
memset(&CardStatus, 0, sizeof(card_stat));
|
||||
memcpy(&gci, FileBuffer, sizeof(GCI));
|
||||
|
||||
memcpy(&CardStatus.gamecode, &gci.gamecode, 4);
|
||||
memcpy(&CardStatus.company, &gci.company, 2);
|
||||
CardStatus.banner_fmt = gci.banner_fmt;
|
||||
memcpy(&CardStatus.filename, &gci.filename, CARD_FILENAMELEN);
|
||||
CardStatus.time = gci.time;
|
||||
CardStatus.icon_addr = gci.icon_addr;
|
||||
CardStatus.icon_fmt = gci.icon_fmt;
|
||||
CardStatus.icon_speed = gci.icon_speed;
|
||||
CardStatus.len = gci.filesize8 * 8192;
|
||||
CardStatus.comment_addr = gci.comment_addr;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* CardGetDirectory
|
||||
*
|
||||
* Returns number of files found on a card.
|
||||
****************************************************************************/
|
||||
int CardGetDirectory (int slot){
|
||||
int err;
|
||||
char company[4];
|
||||
char gamecode[6];
|
||||
|
||||
company[2] = gamecode[4] = 0;
|
||||
|
||||
/*** Clear the work area ***/
|
||||
memset (SysArea, 0, CARD_WORKAREA);
|
||||
|
||||
/*** Initialise the Card system, show all ***/
|
||||
CARD_Init (NULL, NULL);
|
||||
|
||||
/*** Try to mount the card ***/
|
||||
err = MountCard(slot);
|
||||
if (err){
|
||||
WaitCardError("CardMount",CARD_GetErrorCode(slot));
|
||||
return 0; /*** Unable to mount the card ***/
|
||||
}
|
||||
|
||||
/*** Retrieve the directory listing ***/
|
||||
cardcount = 0;
|
||||
err = CARD_FindFirst (slot, &CardDir, true);
|
||||
while (err != CARD_ERROR_NOFILE)
|
||||
{
|
||||
memcpy (&CardList[cardcount], &CardDir, sizeof (card_dir));
|
||||
memset (filelist[cardcount], 0, 1024);
|
||||
memcpy (company, &CardDir.company, 2);
|
||||
memcpy (gamecode, &CardDir.gamecode, 4);
|
||||
sprintf (filelist[cardcount], "%s-%s-%s", company, gamecode, CardDir.filename);
|
||||
cardcount++;
|
||||
err = CARD_FindNext (&CardDir);
|
||||
}
|
||||
|
||||
/*** Release as soon as possible ***/
|
||||
CARD_Unmount (slot);
|
||||
|
||||
maxfile = cardcount;
|
||||
return cardcount;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* CardListFiles
|
||||
****************************************************************************/
|
||||
void CardListFiles (){
|
||||
int i;
|
||||
char company[4];
|
||||
char gamecode[6];
|
||||
|
||||
company[2] = 0;
|
||||
gamecode[4] = 0;
|
||||
|
||||
for (i = 0; i < cardcount; i++)
|
||||
{
|
||||
memcpy (company, &CardList[i].company, 2);
|
||||
memcpy (gamecode, &CardList[i].gamecode, 4);
|
||||
printf ("%s %s %s\n", company, gamecode, CardList[i].filename);
|
||||
}
|
||||
}
|
||||
/****************************************************************************
|
||||
* CardReadFileHeader
|
||||
*
|
||||
* Retrieve a file header from the previously populated list.
|
||||
****************************************************************************/
|
||||
int CardReadFileHeader (int slot, int id){
|
||||
int err;
|
||||
char company[4];
|
||||
char gamecode[6];
|
||||
|
||||
if (id >= cardcount){
|
||||
WaitPrompt("Bad id");
|
||||
return 0; /*** Bad id ***/
|
||||
}
|
||||
|
||||
/*** Clear the work buffers ***/
|
||||
memset (SysArea, 0, CARD_WORKAREA);
|
||||
company[2] = 0;
|
||||
gamecode[4] = 0;
|
||||
|
||||
memcpy (company, &CardList[id].company, 2);
|
||||
memcpy (gamecode, &CardList[id].gamecode, 4);
|
||||
|
||||
/*** Initialise for this company ***/
|
||||
CARD_Init (gamecode, company);
|
||||
|
||||
/*** Mount the card ***/
|
||||
err = MountCard (slot);
|
||||
if (err){
|
||||
WaitCardError("CardMount",CARD_GetErrorCode(slot));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*** Get card status info ***/
|
||||
CARD_GetStatus (slot, CardFile.filenum, &CardStatus);
|
||||
|
||||
GCIMakeHeader();
|
||||
|
||||
/*** Unmount the card ***/
|
||||
CARD_Unmount (slot);
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* CardReadFile
|
||||
*
|
||||
* Retrieve a file from the previously populated list.
|
||||
* Place in filebuffer space, for collection by SMB write.
|
||||
****************************************************************************/
|
||||
int CardReadFile (int slot, int id){
|
||||
int bytesdone = 0;
|
||||
int err;
|
||||
u32 SectorSize;
|
||||
char company[4];
|
||||
char gamecode[6];
|
||||
int filesize;
|
||||
|
||||
if (id >= cardcount){
|
||||
WaitPrompt("Bad id");
|
||||
return 0; /*** Bad id ***/
|
||||
}
|
||||
|
||||
/*** Clear the work buffers ***/
|
||||
memset (FileBuffer, 0, MAXFILEBUFFER);
|
||||
memset (SysArea, 0, CARD_WORKAREA);
|
||||
company[2] = 0;
|
||||
gamecode[4] = 0;
|
||||
|
||||
memcpy (company, &CardList[id].company, 2);
|
||||
memcpy (gamecode, &CardList[id].gamecode, 4);
|
||||
|
||||
/*** Initialise for this company ***/
|
||||
CARD_Init (gamecode, company);
|
||||
|
||||
/*** Mount the card ***/
|
||||
err = MountCard (slot);
|
||||
if (err){
|
||||
WaitCardError("CardMount",CARD_GetErrorCode(slot));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*** Retrieve sector size ***/
|
||||
CARD_GetSectorSize (slot, &SectorSize);
|
||||
|
||||
/*** Open the file ***/
|
||||
err = CARD_Open (slot, (char *) &CardList[id].filename, &CardFile);
|
||||
if (err)
|
||||
{
|
||||
CARD_Unmount (slot);
|
||||
WaitCardError("CardOpen",CARD_GetErrorCode(slot));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*** Get card status info ***/
|
||||
CARD_GetStatus (slot, CardFile.filenum, &CardStatus);
|
||||
|
||||
GCIMakeHeader();
|
||||
|
||||
/*** Copy the file contents to the buffer ***/
|
||||
filesize = CardFile.len;
|
||||
|
||||
while (bytesdone < filesize)
|
||||
{
|
||||
CARD_Read (&CardFile, FileBuffer + MCDATAOFFSET + bytesdone, SectorSize,
|
||||
bytesdone);
|
||||
bytesdone += SectorSize;
|
||||
}
|
||||
|
||||
/*** Close the file ***/
|
||||
CARD_Close (&CardFile);
|
||||
|
||||
/*** Unmount the card ***/
|
||||
CARD_Unmount (slot);
|
||||
|
||||
return filesize + MCDATAOFFSET;
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* CardWriteFile
|
||||
*
|
||||
* Relies on *GOOD* data being placed in the FileBuffer prior to calling.
|
||||
* See ReadSMBImage
|
||||
****************************************************************************/
|
||||
int CardWriteFile (int slot) {
|
||||
char company[4];
|
||||
char gamecode[6];
|
||||
char filename[CARD_FILENAMELEN];
|
||||
int err;
|
||||
u32 SectorSize;
|
||||
int offset;
|
||||
int written;
|
||||
int filelen;
|
||||
|
||||
company[2] = gamecode[4] = 0;
|
||||
|
||||
memset (SysArea, 0, CARD_WORKAREA);
|
||||
memset(filename, 0, CARD_FILENAMELEN);
|
||||
ExtractGCIHeader();
|
||||
memcpy(company, &gci.company, 2);
|
||||
memcpy(gamecode, &gci.gamecode, 4);
|
||||
memcpy(filename, &gci.filename, CARD_FILENAMELEN);
|
||||
filelen = gci.filesize8 * 8192;
|
||||
|
||||
/*** Init system ***/
|
||||
CARD_Init (gamecode, company);
|
||||
|
||||
err = MountCard(slot);
|
||||
if (err){
|
||||
WaitCardError("CardMount",CARD_GetErrorCode(slot));
|
||||
return 0;
|
||||
}
|
||||
|
||||
CARD_GetSectorSize (slot, &SectorSize);
|
||||
|
||||
/*** If this file exists, abort ***/
|
||||
err = CARD_FindFirst (slot, &CardDir, false);
|
||||
while (err != CARD_ERROR_NOFILE){
|
||||
if (strcmp ((char *) CardDir.filename, (char *)filename) == 0){
|
||||
/*** Found the file - abort ***/
|
||||
CARD_Unmount (slot);
|
||||
WaitCardError("File already exists",CARD_GetErrorCode(slot));
|
||||
return 0;
|
||||
}
|
||||
err = CARD_FindNext (&CardDir);
|
||||
}
|
||||
|
||||
CARD_SetCompany(company);
|
||||
CARD_SetGamecode(gamecode);
|
||||
|
||||
/*** Now restore the file from backup ***/
|
||||
err = CARD_Create (slot, (char *) filename, filelen, &CardFile);
|
||||
if (err){
|
||||
CARD_Unmount (slot);
|
||||
WaitCardError("CardCreate",CARD_GetErrorCode(slot));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*** Now write the file data, in sector sized chunks ***/
|
||||
offset = 0;
|
||||
while (offset < filelen){
|
||||
if ((offset + SectorSize) <= filelen){
|
||||
written = CARD_Write (&CardFile, FileBuffer + MCDATAOFFSET + offset, SectorSize, offset);
|
||||
}
|
||||
else{
|
||||
written = CARD_Write (&CardFile, FileBuffer + MCDATAOFFSET + offset, ((offset + SectorSize) - filelen), offset);
|
||||
}
|
||||
offset += SectorSize;
|
||||
}
|
||||
|
||||
/*** Finally, update the status ***/
|
||||
|
||||
CARD_SetStatus (slot, CardFile.filenum, &CardStatus);
|
||||
|
||||
|
||||
CARD_Close (&CardFile);
|
||||
CARD_Unmount (slot);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void WaitCardError(char *src, int error) {
|
||||
char msg[1024], err[256];
|
||||
|
||||
switch (error) {
|
||||
case CARD_ERROR_BUSY:
|
||||
sprintf(err, "Busy");
|
||||
break;
|
||||
case CARD_ERROR_WRONGDEVICE:
|
||||
sprintf(err, "Wrong device in slot");
|
||||
break;
|
||||
case CARD_ERROR_NOCARD:
|
||||
sprintf(err, "No Card");
|
||||
break;
|
||||
case CARD_ERROR_NOFILE:
|
||||
sprintf(err, "No File");
|
||||
break;
|
||||
case CARD_ERROR_IOERROR:
|
||||
sprintf(err, "Internal EXI I/O error");
|
||||
break;
|
||||
case CARD_ERROR_BROKEN:
|
||||
sprintf(err, "File/Dir entry broken");
|
||||
break;
|
||||
case CARD_ERROR_EXIST:
|
||||
sprintf(err, "File already exists");
|
||||
break;
|
||||
case CARD_ERROR_NOENT:
|
||||
sprintf(err, "No empty blocks");
|
||||
break;
|
||||
case CARD_ERROR_INSSPACE:
|
||||
sprintf(err, "Not enough space");
|
||||
break;
|
||||
case CARD_ERROR_NOPERM:
|
||||
sprintf(err, "No permission");
|
||||
break;
|
||||
case CARD_ERROR_LIMIT:
|
||||
sprintf(err, "Card size limit reached");
|
||||
break;
|
||||
case CARD_ERROR_NAMETOOLONG:
|
||||
sprintf(err, "Filename too long");
|
||||
break;
|
||||
case CARD_ERROR_ENCODING:
|
||||
sprintf(err, "Font encoding mismatch");
|
||||
break;
|
||||
case CARD_ERROR_CANCELED:
|
||||
sprintf(err, "Card operation cancelled");
|
||||
break;
|
||||
case CARD_ERROR_FATAL_ERROR:
|
||||
sprintf(err, "Fatal error");
|
||||
break;
|
||||
case CARD_ERROR_READY:
|
||||
sprintf(err, "Ready");
|
||||
break;
|
||||
default:
|
||||
sprintf(err, "Unknown");
|
||||
break;
|
||||
}
|
||||
sprintf(msg, "MemCard Error: %s - %s", src, err);
|
||||
|
||||
WaitPrompt(msg);
|
||||
|
||||
|
||||
}
|
||||
void MC_DeleteMode(int slot) {
|
||||
int memitems, err;
|
||||
int selected = 0;
|
||||
clearRightPane();
|
||||
DrawText(388,160,"D e l e t e M o d e");
|
||||
writeStatusBar("Choose a file with UP button or DOWN button ", "Press A button to delete ") ;
|
||||
char msg[1024];
|
||||
|
||||
/*** Get the directory listing from the memory card ***/
|
||||
memitems = CardGetDirectory (slot);
|
||||
|
||||
/*** If it's a blank card, get out of here ***/
|
||||
if (!memitems)
|
||||
{WaitPrompt ("No saved games to delete !");}
|
||||
else
|
||||
{
|
||||
// TODO: implement showselector
|
||||
selected = ShowSelector ();
|
||||
if (cancel) {WaitPrompt ("delete action cancelled !");}
|
||||
else{
|
||||
// selected = 1;
|
||||
|
||||
/*** Delete the file ***/
|
||||
sprintf(msg, "Deleting \"%s\"", CardList[selected].filename);
|
||||
writeStatusBar(msg,"");
|
||||
//WaitPrompt(msg);
|
||||
|
||||
CARD_Init(CardList[selected].gamecode, CardList[selected].company);
|
||||
|
||||
/*** Try to mount the card ***/
|
||||
err = MountCard(slot);
|
||||
if (err) {
|
||||
WaitCardError("MCDel Mount", err);
|
||||
return; /*** Unable to mount the card ***/
|
||||
}
|
||||
|
||||
err = CARD_Delete(slot, (char *) &CardList[selected].filename);
|
||||
if (err) {
|
||||
WaitCardError("MCDel", err);
|
||||
} else {
|
||||
WaitPrompt("Delete complete");
|
||||
}
|
||||
|
||||
CARD_Unmount(slot);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
18
source/mcard.h
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/****************************************************************************
|
||||
* mcard support prototypes
|
||||
****************************************************************************/
|
||||
#ifndef _MCARDSUP_
|
||||
#define _MCARDSUP_
|
||||
|
||||
void GCIMakeHeader();
|
||||
void ExtractGCIHeader();
|
||||
int MountCard(int cslot);
|
||||
int CardGetDirectory (int slot);
|
||||
void CardListFiles ();
|
||||
int CardReadFileHeader (int slot, int id);
|
||||
int CardReadFile (int slot, int id);
|
||||
int CardWriteFile (int slot);
|
||||
void MC_DeleteMode(int slot);
|
||||
void WaitCardError(char *src, int error);
|
||||
|
||||
#endif
|
||||
255
source/sdsupp.c
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
/****************************************************************************
|
||||
* SD Card Support Functions
|
||||
****************************************************************************/
|
||||
#include <gccore.h>
|
||||
#include <network.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
//#include <sdcard.h>
|
||||
#include <fat.h>
|
||||
#include <sys/dir.h>
|
||||
|
||||
#include "sdsupp.h"
|
||||
#include "freetype.h"
|
||||
#include "gci.h"
|
||||
|
||||
#define PAGESIZE 20
|
||||
#define PADCAL 80
|
||||
|
||||
/*** Memory Card FileBuffer ***/
|
||||
extern u8 FileBuffer[];
|
||||
extern u8 filelist[1024][1024];
|
||||
extern u32 maxfile;
|
||||
|
||||
int SDSaveMCImage (){
|
||||
|
||||
char filename[1024];
|
||||
char tfile[40];
|
||||
char company[4];
|
||||
char gamecode[6];
|
||||
int bytesToWrite = 0;
|
||||
//sd_file *handle;
|
||||
FILE *handle;
|
||||
GCI thisgci;
|
||||
|
||||
/*** Make a copy of the Card Dir ***/
|
||||
memcpy (&thisgci, FileBuffer, sizeof (GCI));
|
||||
memset( tfile, 0, 40 );
|
||||
company[2] = 0;
|
||||
gamecode[4] = 0;
|
||||
memcpy (company, &thisgci.company, 2);
|
||||
memcpy (gamecode, &thisgci.gamecode, 4);
|
||||
memcpy (tfile, &thisgci.filename, CARD_FILENAMELEN);
|
||||
|
||||
sprintf (filename, "fatX:/%s", MCSAVES);
|
||||
#ifdef HW_RVL
|
||||
filename[3]=48+PI_INTERNAL_SD;
|
||||
#else
|
||||
filename[3]=48+PI_SDGECKO_A;
|
||||
#endif
|
||||
mkdir(filename, S_IREAD | S_IWRITE);
|
||||
|
||||
sprintf (filename, "fatX:/%s/%s-%s-%s.gci", MCSAVES, company, gamecode,tfile);
|
||||
#ifdef HW_RVL
|
||||
filename[3]=48+PI_INTERNAL_SD;
|
||||
#else
|
||||
filename[3]=48+PI_SDGECKO_A;
|
||||
#endif
|
||||
|
||||
/*** Open SD Card file ***/
|
||||
//handle = SDCARD_OpenFile (filename, "wb");
|
||||
handle = fopen ( filename , "wb" );
|
||||
if (handle <= 0){
|
||||
char msg[100];
|
||||
sprintf(msg, "Couldn't save %s", filename);
|
||||
WaitPrompt (msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bytesToWrite = (thisgci.filesize8 * 8192) + MCDATAOFFSET;
|
||||
//SDCARD_WriteFile (handle, FileBuffer, bytesToWrite);
|
||||
//SDCARD_CloseFile (handle);
|
||||
fwrite (FileBuffer , 1 , bytesToWrite , handle );
|
||||
fclose (handle);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SDLoadMCImage(char *sdfilename){
|
||||
|
||||
//sd_file *handle;
|
||||
FILE *handle;
|
||||
char filename[1024];
|
||||
char msg[256];
|
||||
//int offset = 0;
|
||||
//int bytesToRead = 0;
|
||||
long bytesToRead = 0;
|
||||
|
||||
/*** Make fullpath filename ***/
|
||||
//sprintf (filename, "dev0:\\%s\\%s", MCSAVES, sdfilename);
|
||||
sprintf (filename, "fatX:/%s/%s", MCSAVES, sdfilename);
|
||||
#ifdef HW_RVL
|
||||
filename[3]=48+PI_INTERNAL_SD;
|
||||
#else
|
||||
filename[3]=48+PI_SDGECKO_A;
|
||||
#endif
|
||||
//SDCARD_Init ();
|
||||
|
||||
/*** Does this file exist ? ***/
|
||||
/*if (SDCARD_SeekFile(filename, 0, SDCARD_SEEK_SET) != SDCARD_ERROR_READY){
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
/*** Open the SD Card file ***/
|
||||
//handle = SDCARD_OpenFile (filename, "rb");
|
||||
handle = fopen ( filename , "rb" );
|
||||
if (handle <= 0){
|
||||
sprintf(msg, "Couldn't open %s", filename);
|
||||
WaitPrompt (msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* if (handle == NULL){
|
||||
WaitPrompt ("Unable to open file!");
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
// obtain file size:
|
||||
fseek (handle , 0 , SEEK_END);
|
||||
bytesToRead = ftell (handle);
|
||||
rewind (handle);
|
||||
|
||||
//bytesToRead = SDCARD_GetFileSize(handle);
|
||||
if (bytesToRead <= 0){
|
||||
sprintf(msg, "Incorrect file size %ld .", bytesToRead);
|
||||
WaitPrompt (msg);
|
||||
//WaitPrompt("Incorrect file size.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*** Read the file ***/
|
||||
//SDCARD_ReadFile (handle, FileBuffer, bytesToRead);
|
||||
fread (FileBuffer,1,bytesToRead,handle);
|
||||
|
||||
//sprintf(msg, "Offset: %d", bytesToRead);
|
||||
//WaitPrompt (msg);
|
||||
/*** Close the file ***/
|
||||
//SDCARD_CloseFile (handle);
|
||||
fclose (handle);
|
||||
|
||||
return bytesToRead;
|
||||
}
|
||||
|
||||
int SDLoadMCImageHeader(char *sdfilename){
|
||||
|
||||
FILE *handle;
|
||||
char filename[1024];
|
||||
char msg[256];
|
||||
//int offset = 0;
|
||||
//int bytesToRead = 0;
|
||||
long bytesToRead = 0;
|
||||
int header_size = 64;
|
||||
|
||||
/*** Make fullpath filename ***/
|
||||
sprintf (filename, "fatX:/%s/%s", MCSAVES, sdfilename);
|
||||
#ifdef HW_RVL
|
||||
filename[3]=48+PI_INTERNAL_SD;
|
||||
#else
|
||||
filename[3]=48+PI_SDGECKO_A;
|
||||
#endif
|
||||
|
||||
/*** Open the SD Card file ***/
|
||||
//handle = SDCARD_OpenFile (filename, "rb");
|
||||
handle = fopen ( filename , "rb" );
|
||||
if (handle <= 0){
|
||||
sprintf(msg, "Couldn't open %s", filename);
|
||||
WaitPrompt (msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// obtain file size:
|
||||
fseek (handle , 0 , SEEK_END);
|
||||
bytesToRead = ftell (handle);
|
||||
rewind (handle);
|
||||
if (bytesToRead < 64){//We don't want to read something smaller than the header
|
||||
sprintf(msg, "Incorrect file size %ld . Not GCI File", bytesToRead);
|
||||
WaitPrompt (msg);
|
||||
//WaitPrompt("Incorrect file size.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*** Read the file header ***/
|
||||
fread (FileBuffer,1,header_size,handle);
|
||||
/*** Close the file ***/
|
||||
fclose (handle);
|
||||
|
||||
return bytesToRead;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* SDGetFileList
|
||||
*
|
||||
* Get the directory listing from SD Card
|
||||
****************************************************************************/
|
||||
int SDGetFileList (){
|
||||
|
||||
int filecount = 0;
|
||||
DIR_ITER * dir;
|
||||
static char namefile[256*4]; // reserva espacio suficiente para UTF-8
|
||||
static struct stat filestat;
|
||||
|
||||
char filename[1024];
|
||||
sprintf (filename, "fatX:/%s/", MCSAVES);
|
||||
#ifdef HW_RVL
|
||||
filename[3]=48+PI_INTERNAL_SD;
|
||||
#else
|
||||
filename[3]=48+PI_SDGECKO_A;
|
||||
#endif
|
||||
|
||||
dir = diropen(filename);
|
||||
|
||||
while(1)
|
||||
{
|
||||
if(dirnext(dir, namefile, &filestat)!=0) break; // si no hay mas entradas en el directorio, sal
|
||||
|
||||
if(filestat.st_mode & S_IFDIR) // es el nombre de un directorio
|
||||
{// namefile contiene el nombre del directorio en formato UTF-8,que puede ser "." o ".." tambien
|
||||
}
|
||||
else
|
||||
{// namefile contiene el nombre del fichero en formato UTF-8
|
||||
strcpy (filelist[filecount], namefile);
|
||||
filecount++;
|
||||
}
|
||||
}
|
||||
|
||||
dirclose(dir); // cierra el directorio
|
||||
maxfile = filecount;
|
||||
return filecount;
|
||||
|
||||
/* int entries = 0;
|
||||
int filecount = 0;
|
||||
char filename[1024];
|
||||
//DIR *sddir = NULL;
|
||||
DIR_ITER *sddir = NULL;
|
||||
|
||||
SDCARD_Init ();
|
||||
|
||||
sprintf (filename, "dev0:\\%s\\", MCSAVES);
|
||||
|
||||
entries = SDCARD_ReadDir (filename, &sddir);
|
||||
|
||||
while (entries){
|
||||
strcpy (filelist[filecount], sddir[filecount].fname);
|
||||
filecount++;
|
||||
entries--;
|
||||
}
|
||||
|
||||
free(sddir);
|
||||
|
||||
maxfile = filecount;
|
||||
return filecount;
|
||||
*/
|
||||
}
|
||||
6
source/sdsupp.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#define MCSAVES "MCBACKUP"
|
||||
|
||||
int SDSaveMCImage ();
|
||||
int SDLoadMCImage(char *sdfilename);
|
||||
int SDLoadMCImageHeader(char *sdfilename);
|
||||
int SDGetFileList ();
|
||||
BIN
source/ttf/font.ttf
Normal file
BIN
source/wiibk.bmp
Normal file
|
After Width: | Height: | Size: 844 KiB |