[1.0.8 - April 4, 2009]

* "Match Wii Game" controls option! Games that have a Wii equivalent can be
  played using the controls for that Wii game. For example all Zelda games
  can be played with Twilight Princess controls. See the Instructions section
  below for important details.
* Rotation/Tilt sensor games all work
* Solar sensors (Boktai 1/2/3)
* Rumble (except for games that rely on Gameboy Player)
* Keyboard
* PAL support, finally!
* New scaling options, choose how much stretching you want
* Colourised games now partially work but still have distortion
* "Corvette" no longer has a screwed up palette (but still crashes)
* Triggers net reconnection on SMB failure
* Source code refactored, and project file added
* Instructions section added to this readme file
This commit is contained in:
dborth 2009-04-10 03:16:28 +00:00
parent 926ad163f3
commit 2d9b7ef1f9
133 changed files with 22767 additions and 10687 deletions

View File

@ -29,7 +29,7 @@ INCLUDES := source/vba source/ngc source/unzip
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) \ CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) \
-DNGC -DNO_SOUND -DUSE_VM -DWORDS_BIGENDIAN \ -DNGC -DUSE_VM -DWORDS_BIGENDIAN \
-DC_CORE -D__ppc__ -D__POWERPC__ -DFINAL_VERSION \ -DC_CORE -D__ppc__ -D__POWERPC__ -DFINAL_VERSION \
-DSDL -DNO_PNG -DHAVE_ZUTIL_H \ -DSDL -DNO_PNG -DHAVE_ZUTIL_H \
-D_SZ_ONE_DIRECTORY -D_LZMA_IN_CB -D_LZMA_OUT_READ \ -D_SZ_ONE_DIRECTORY -D_LZMA_IN_CB -D_LZMA_OUT_READ \
@ -41,7 +41,7 @@ LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# any extra libraries we wish to link with # any extra libraries we wish to link with
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
LIBS := -lpngu -lpng -lmxml -lmetaphrasis -lfat -lz -logc -lfreetype LIBS := -lpngu -lpng -lmxml -lbba -ltinysmb -lfat -lz -logc -lm -lfreetype
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing # list of directories containing libraries, this must be the top level containing
@ -72,7 +72,6 @@ sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf))) TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf)))
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png))) PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
PCMFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pcm)))
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C # use CXX for linking C++ projects, CC for standard C
@ -85,8 +84,8 @@ endif
export OFILES := $(addsuffix .o,$(BINFILES)) \ export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
$(TTFFILES:.ttf=.ttf.o) $(PNGFILES:.png=.png.o) \ $(TTFFILES:.ttf=.ttf.o) \
$(PCMFILES:.pcm=.pcm.o) $(PNGFILES:.png=.png.o)
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# build a list of include paths # build a list of include paths
@ -147,10 +146,6 @@ $(OUTPUT).elf: $(OFILES)
@echo $(notdir $<) @echo $(notdir $<)
$(bin2o) $(bin2o)
%.pcm.o : %.pcm
@echo $(notdir $<)
$(bin2o)
-include $(DEPENDS) -include $(DEPENDS)
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------

View File

@ -41,8 +41,7 @@ LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map -Wl,--cref
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# any extra libraries we wish to link with # any extra libraries we wish to link with
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
LIBS := -ldb -ldi -lpngu -lpng -lmxml -lmetaphrasis \ LIBS := -ldi -lpngu -lpng -lmxml -lfat -lwiiuse -lz -lbte -logc -lm -lfreetype -ltinysmb
-lfat -lwiiuse -lz -lbte -logc -lasnd -ltremor -lfreetype -ltinysmb
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing # list of directories containing libraries, this must be the top level containing
@ -73,8 +72,6 @@ sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf))) TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf)))
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png))) PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
OGGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ogg)))
PCMFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pcm)))
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C # use CXX for linking C++ projects, CC for standard C
@ -87,8 +84,8 @@ endif
export OFILES := $(addsuffix .o,$(BINFILES)) \ export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
$(TTFFILES:.ttf=.ttf.o) $(PNGFILES:.png=.png.o) \ $(TTFFILES:.ttf=.ttf.o) \
$(OGGFILES:.ogg=.ogg.o) $(PCMFILES:.pcm=.pcm.o) $(PNGFILES:.png=.png.o)
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# build a list of include paths # build a list of include paths
@ -149,14 +146,6 @@ $(OUTPUT).elf: $(OFILES)
@echo $(notdir $<) @echo $(notdir $<)
$(bin2o) $(bin2o)
%.ogg.o : %.ogg
@echo $(notdir $<)
$(bin2o)
%.pcm.o : %.pcm
@echo $(notdir $<)
$(bin2o)
-include $(DEPENDS) -include $(DEPENDS)
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------

View File

@ -1,718 +0,0 @@
/*
* FreeTypeGX is a wrapper class for libFreeType which renders a compiled
* FreeType parsable font into a GX texture for Wii homebrew development.
* Copyright (C) 2008 Armin Tamzarian
* Modified by Tantric, 2009
*
* This file is part of FreeTypeGX.
*
* FreeTypeGX is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FreeTypeGX 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FreeTypeGX. If not, see <http://www.gnu.org/licenses/>.
*/
#include "FreeTypeGX.h"
/**
* Default constructor for the FreeTypeGX class.
*
* @param textureFormat Optional format (GX_TF_*) of the texture as defined by the libogc gx.h header file. If not specified default value is GX_TF_RGBA8.
* @param vertexIndex Optional vertex format index (GX_VTXFMT*) of the glyph textures as defined by the libogc gx.h header file. If not specified default value is GX_VTXFMT1.
*/
FreeTypeGX::FreeTypeGX(uint8_t textureFormat, uint8_t vertexIndex) {
FT_Init_FreeType(&this->ftLibrary);
this->textureFormat = textureFormat;
this->setVertexFormat(vertexIndex);
this->setCompatibilityMode(FTGX_COMPATIBILITY_NONE);
}
/**
* Default destructor for the FreeTypeGX class.
*/
FreeTypeGX::~FreeTypeGX() {
this->unloadFont();
}
/**
* Convert a short char sctring to a wide char string.
*
* This routine converts a supplied shot character string into a wide character string.
* Note that it is the user's responsibility to clear the returned buffer once it is no longer needed.
*
* @param strChar Character string to be converted.
* @return Wide character representation of supplied character string.
*/
wchar_t* FreeTypeGX::charToWideChar(char* strChar) {
wchar_t *strWChar;
strWChar = new wchar_t[strlen(strChar) + 1];
char *tempSrc = strChar;
wchar_t *tempDest = strWChar;
while((*tempDest++ = *tempSrc++));
return strWChar;
}
/**
*
* \overload
*/
wchar_t* FreeTypeGX::charToWideChar(const char* strChar) {
return FreeTypeGX::charToWideChar((char*) strChar);
}
/**
* Setup the vertex attribute formats for the glyph textures.
*
* This function sets up the vertex format for the glyph texture on the specified vertex format index.
* Note that this function should not need to be called except if the vertex formats are cleared or the specified
* vertex format index is modified.
*
* @param vertexIndex Vertex format index (GX_VTXFMT*) of the glyph textures as defined by the libogc gx.h header file.
*/
void FreeTypeGX::setVertexFormat(uint8_t vertexIndex) {
this->vertexIndex = vertexIndex;
GX_SetVtxAttrFmt(this->vertexIndex, GX_VA_POS, GX_POS_XY, GX_S16, 0);
GX_SetVtxAttrFmt(this->vertexIndex, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GX_SetVtxAttrFmt(this->vertexIndex, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
}
/**
* Sets the TEV and VTX rendering compatibility requirements for the class.
*
* This sets up the default TEV opertion and VTX descriptions rendering values for the class. This ensures that FreeTypeGX
* can remain compatible with external liraries or project code. Certain external libraries or code by design or lack of
* foresight assume that the TEV opertion and VTX descriptions values will remain constant or are always returned to a
* certain value. This will enable compatibility with those libraries and any other code which cannot or will not be changed.
*
* @param compatibilityMode Compatibility descritor (FTGX_COMPATIBILITY_*) as defined in FreeTypeGX.h
*/
void FreeTypeGX::setCompatibilityMode(uint32_t compatibilityMode) {
this->compatibilityMode = compatibilityMode;
}
/**
* Sets the TEV operation and VTX descriptor values after texture rendering it complete.
*
* This function calls the GX_SetTevOp and GX_SetVtxDesc functions with the compatibility parameters specified
* in setCompatibilityMode.
*/
void FreeTypeGX::setDefaultMode() {
if(this->compatibilityMode) {
switch(this->compatibilityMode & 0x00FF) {
case FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_MODULATE:
GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE);
break;
case FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_DECAL:
GX_SetTevOp(GX_TEVSTAGE0, GX_DECAL);
break;
case FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_BLEND:
GX_SetTevOp(GX_TEVSTAGE0, GX_BLEND);
break;
case FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_REPLACE:
GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE);
break;
case FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_PASSCLR:
GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
break;
default:
break;
}
switch(this->compatibilityMode & 0xFF00) {
case FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_NONE:
GX_SetVtxDesc(GX_VA_TEX0, GX_NONE);
break;
case FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_DIRECT:
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
break;
case FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_INDEX8:
GX_SetVtxDesc(GX_VA_TEX0, GX_INDEX8);
break;
case FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_INDEX16:
GX_SetVtxDesc(GX_VA_TEX0, GX_INDEX16);
break;
default:
break;
}
}
}
/**
* Loads and processes a specified true type font buffer to a specific point size.
*
* This routine takes a precompiled true type font buffer and loads the necessary processed data into memory. This routine should be called before drawText will succeed.
*
* @param fontBuffer A pointer in memory to a precompiled true type font buffer.
* @param bufferSize Size of the true type font buffer in bytes.
* @param pointSize The desired point size this wrapper's configured font face.
* @param cacheAll Optional flag to specify if all font characters should be cached when the class object is created. If specified as false the characters only become cached the first time they are used. If not specified default value is false.
*/
uint16_t FreeTypeGX::loadFont(uint8_t* fontBuffer, FT_Long bufferSize, FT_UInt pointSize, bool cacheAll) {
this->unloadFont();
this->ftPointSize = pointSize;
FT_New_Memory_Face(this->ftLibrary, (FT_Byte *)fontBuffer, bufferSize, 0, &this->ftFace);
if(this->ftPointSize > 0)
FT_Set_Pixel_Sizes(this->ftFace, 0, this->ftPointSize);
this->ftSlot = this->ftFace->glyph;
this->ftKerningEnabled = FT_HAS_KERNING(this->ftFace);
if (cacheAll) {
return this->cacheGlyphDataComplete();
}
return 0;
}
/**
*
* \overload
*/
uint16_t FreeTypeGX::loadFont(const uint8_t* fontBuffer, FT_Long bufferSize, FT_UInt pointSize, bool cacheAll) {
return this->loadFont((uint8_t *)fontBuffer, bufferSize, pointSize, cacheAll);
}
/**
* Clears all loaded font glyph data.
*
* This routine clears all members of the font map structure and frees all allocated memory back to the system.
*/
void FreeTypeGX::unloadFont() {
if(this->fontData.size() == 0)
return;
GX_DrawDone();
GX_Flush();
for( std::map<wchar_t, ftgxCharData>::iterator i = this->fontData.begin(); i != this->fontData.end(); i++) {
free(i->second.glyphDataTexture);
}
this->fontData.clear();
}
void FreeTypeGX::changeSize(FT_UInt pointSize) {
this->unloadFont();
this->ftPointSize = pointSize;
FT_Set_Pixel_Sizes(this->ftFace, 0, this->ftPointSize);
}
/**
* Adjusts the texture data buffer to necessary width for a given texture format.
*
* This routine determines adjusts the given texture width into the required width to hold the necessary texture data for proper alignment.
*
* @param textureWidth The initial guess for the texture width.
* @param textureFormat The texture format to which the data is to be converted.
* @return The correctly adjusted texture width.
*/
uint16_t FreeTypeGX::adjustTextureWidth(uint16_t textureWidth, uint8_t textureFormat) {
uint16_t alignment;
switch(textureFormat) {
case GX_TF_I4: /* 8x8 Tiles - 4-bit Intensity */
case GX_TF_I8: /* 8x4 Tiles - 8-bit Intensity */
case GX_TF_IA4: /* 8x4 Tiles - 4-bit Intensity, , 4-bit Alpha */
alignment = 8;
break;
case GX_TF_IA8: /* 4x4 Tiles - 8-bit Intensity, 8-bit Alpha */
case GX_TF_RGB565: /* 4x4 Tiles - RGB565 Format */
case GX_TF_RGB5A3: /* 4x4 Tiles - RGB5A3 Format */
case GX_TF_RGBA8: /* 4x4 Tiles - RGBA8 Dual Cache Line Format */
default:
alignment = 4;
break;
}
return textureWidth % alignment == 0 ? textureWidth : alignment + textureWidth - (textureWidth % alignment);
}
/**
* Adjusts the texture data buffer to necessary height for a given texture format.
*
* This routine determines adjusts the given texture height into the required height to hold the necessary texture data for proper alignment.
*
* @param textureHeight The initial guess for the texture height.
* @param textureFormat The texture format to which the data is to be converted.
* @return The correctly adjusted texture height.
*/
uint16_t FreeTypeGX::adjustTextureHeight(uint16_t textureHeight, uint8_t textureFormat) {
uint16_t alignment;
switch(textureFormat) {
case GX_TF_I4: /* 8x8 Tiles - 4-bit Intensity */
alignment = 8;
break;
case GX_TF_I8: /* 8x4 Tiles - 8-bit Intensity */
case GX_TF_IA4: /* 8x4 Tiles - 4-bit Intensity, , 4-bit Alpha */
case GX_TF_IA8: /* 4x4 Tiles - 8-bit Intensity, 8-bit Alpha */
case GX_TF_RGB565: /* 4x4 Tiles - RGB565 Format */
case GX_TF_RGB5A3: /* 4x4 Tiles - RGB5A3 Format */
case GX_TF_RGBA8: /* 4x4 Tiles - RGBA8 Dual Cache Line Format */
default:
alignment = 4;
break;
}
return textureHeight % alignment == 0 ? textureHeight : alignment + textureHeight - (textureHeight % alignment);
}
/**
* Caches the given font glyph in the instance font texture buffer.
*
* This routine renders and stores the requested glyph's bitmap and relevant information into its own quickly addressible
* structure within an instance-specific map.
*
* @param charCode The requested glyph's character code.
* @return A pointer to the allocated font structure.
*/
ftgxCharData *FreeTypeGX::cacheGlyphData(wchar_t charCode) {
FT_UInt gIndex;
uint16_t textureWidth = 0, textureHeight = 0;
gIndex = FT_Get_Char_Index( this->ftFace, charCode );
if (!FT_Load_Glyph(this->ftFace, gIndex, FT_LOAD_DEFAULT )) {
FT_Render_Glyph( this->ftSlot, FT_RENDER_MODE_NORMAL );
if(this->ftSlot->format == FT_GLYPH_FORMAT_BITMAP) {
FT_Bitmap *glyphBitmap = &this->ftSlot->bitmap;
textureWidth = adjustTextureWidth(glyphBitmap->width, this->textureFormat);
textureHeight = adjustTextureHeight(glyphBitmap->rows, this->textureFormat);
this->fontData[charCode] = (ftgxCharData){
this->ftSlot->advance.x >> 6,
gIndex,
textureWidth,
textureHeight,
this->ftSlot->bitmap_top,
this->ftSlot->bitmap_top,
textureHeight - this->ftSlot->bitmap_top,
NULL
};
this->loadGlyphData(glyphBitmap, &this->fontData[charCode]);
return &this->fontData[charCode];
}
}
return NULL;
}
/**
* Locates each character in this wrapper's configured font face and proccess them.
*
* This routine locates each character in the configured font face and renders the glyph's bitmap.
* Each bitmap and relevant information is loaded into its own quickly addressible structure within an instance-specific map.
*/
uint16_t FreeTypeGX::cacheGlyphDataComplete() {
uint16_t i = 0;
FT_UInt gIndex;
FT_ULong charCode = FT_Get_First_Char( this->ftFace, &gIndex );
while ( gIndex != 0 ) {
if(this->cacheGlyphData(charCode) != NULL) {
i++;
}
charCode = FT_Get_Next_Char( this->ftFace, charCode, &gIndex );
}
return i;
}
/**
* Loads the rendered bitmap into the relevant structure's data buffer.
*
* This routine does a simple byte-wise copy of the glyph's rendered 8-bit grayscale bitmap into the structure's buffer.
* Each byte is converted from the bitmap's intensity value into the a uint32_t RGBA value.
*
* @param bmp A pointer to the most recently rendered glyph's bitmap.
* @param charData A pointer to an allocated ftgxCharData structure whose data represent that of the last rendered glyph.
*/
void FreeTypeGX::loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData) {
uint32_t *glyphData = (uint32_t *)memalign(32, charData->textureWidth * charData->textureHeight * 4);
memset(glyphData, 0x00, charData->textureWidth * charData->textureHeight * 4);
for (uint16_t imagePosY = 0; imagePosY < bmp->rows; imagePosY++) {
for (uint16_t imagePosX = 0; imagePosX < bmp->width; imagePosX++) {
uint32_t pixel = (uint32_t) bmp->buffer[imagePosY * bmp->width + imagePosX];
glyphData[imagePosY * charData->textureWidth + imagePosX] = 0x00000000 | (pixel << 24) | (pixel << 16) | (pixel << 8) | pixel;
}
}
switch(this->textureFormat) {
case GX_TF_I4:
charData->glyphDataTexture = Metaphrasis::convertBufferToI4(glyphData, charData->textureWidth, charData->textureHeight);
break;
case GX_TF_I8:
charData->glyphDataTexture = Metaphrasis::convertBufferToI8(glyphData, charData->textureWidth, charData->textureHeight);
break;
case GX_TF_IA4:
charData->glyphDataTexture = Metaphrasis::convertBufferToIA4(glyphData, charData->textureWidth, charData->textureHeight);
break;
case GX_TF_IA8:
charData->glyphDataTexture = Metaphrasis::convertBufferToIA8(glyphData, charData->textureWidth, charData->textureHeight);
break;
case GX_TF_RGB565:
charData->glyphDataTexture = Metaphrasis::convertBufferToRGB565(glyphData, charData->textureWidth, charData->textureHeight);
break;
case GX_TF_RGB5A3:
charData->glyphDataTexture = Metaphrasis::convertBufferToRGB5A3(glyphData, charData->textureWidth, charData->textureHeight);
break;
case GX_TF_RGBA8:
default:
charData->glyphDataTexture = Metaphrasis::convertBufferToRGBA8(glyphData, charData->textureWidth, charData->textureHeight);
break;
}
free(glyphData);
}
/**
* Determines the x offset of the rendered string.
*
* This routine calculates the x offset of the rendered string based off of a supplied positional format parameter.
*
* @param width Current pixel width of the string.
* @param format Positional format of the string.
*/
uint16_t FreeTypeGX::getStyleOffsetWidth(uint16_t width, uint16_t format) {
if (format & FTGX_JUSTIFY_LEFT ) {
return 0;
}
else if (format & FTGX_JUSTIFY_CENTER ) {
return width >> 1;
}
else if (format & FTGX_JUSTIFY_RIGHT ) {
return width;
}
return 0;
}
/**
* Determines the y offset of the rendered string.
*
* This routine calculates the y offset of the rendered string based off of a supplied positional format parameter.
*
* @param offset Current pixel offset data of the string.
* @param format Positional format of the string.
*/
uint16_t FreeTypeGX::getStyleOffsetHeight(ftgxDataOffset offset, uint16_t format) {
if (format & FTGX_ALIGN_TOP ) {
return -offset.max;
}
else if (format & FTGX_ALIGN_MIDDLE ) {
return -offset.max;
}
else if (format & FTGX_ALIGN_BOTTOM ) {
return offset.min;
}
return 0;
}
/**
* Processes the supplied text string and prints the results at the specified coordinates.
*
* This routine processes each character of the supplied text string, loads the relevant preprocessed bitmap buffer,
* a texture from said buffer, and loads the resultant texture into the EFB.
*
* @param x Screen X coordinate at which to output the text.
* @param y Screen Y coordinate at which to output the text. Note that this value corresponds to the text string origin and not the top or bottom of the glyphs.
* @param text NULL terminated string to output.
* @param color Optional color to apply to the text characters. If not specified default value is ftgxWhite: (GXColor){0xff, 0xff, 0xff, 0xff}
* @param textStyle Flags which specify any styling which should be applied to the rendered string.
* @return The number of characters printed.
*/
uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t *text, GXColor color, uint16_t textStyle) {
uint16_t strLength = wcslen(text);
uint16_t x_pos = x, printed = 0;
uint16_t x_offset = 0, y_offset = 0;
GXTexObj glyphTexture;
FT_Vector pairDelta;
if(textStyle & 0x000F) {
x_offset = this->getStyleOffsetWidth(this->getWidth(text), textStyle);
}
if(textStyle & 0x00F0) {
y_offset = this->getStyleOffsetHeight(this->getOffset(text), textStyle);
}
for (uint16_t i = 0; i < strLength; i++) {
ftgxCharData* glyphData = NULL;
if( this->fontData.find(text[i]) != this->fontData.end() ) {
glyphData = &this->fontData[text[i]];
}
else {
glyphData = this->cacheGlyphData(text[i]);
}
if(glyphData != NULL) {
if(this->ftKerningEnabled && i) {
FT_Get_Kerning( this->ftFace, this->fontData[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta );
x_pos += pairDelta.x >> 6;
}
GX_InitTexObj(&glyphTexture, glyphData->glyphDataTexture, glyphData->textureWidth, glyphData->textureHeight, this->textureFormat, GX_CLAMP, GX_CLAMP, GX_FALSE);
this->copyTextureToFramebuffer(&glyphTexture, glyphData->textureWidth, glyphData->textureHeight, x_pos - x_offset, y - glyphData->renderOffsetY - y_offset, color);
x_pos += glyphData->glyphAdvanceX;
printed++;
}
}
if(textStyle & 0x0F00) {
this->drawTextFeature(x - x_offset, y, this->getWidth(text), this->getOffset(text), textStyle, color);
}
return printed;
}
/**
* \overload
*/
uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, wchar_t const *text, GXColor color, uint16_t textStyle) {
return this->drawText(x, y, (wchar_t *)text, color, textStyle);
}
void FreeTypeGX::drawTextFeature(int16_t x, int16_t y, uint16_t width, ftgxDataOffset offsetData, uint16_t format, GXColor color) {
uint16_t featureHeight = this->ftPointSize >> 4 > 0 ? this->ftPointSize >> 4 : 1;
if (format & FTGX_STYLE_UNDERLINE ) {
switch(format & 0x00F0) {
case FTGX_ALIGN_TOP:
this->copyFeatureToFramebuffer(width, featureHeight, x, y + offsetData.max + 1, color);
break;
case FTGX_ALIGN_MIDDLE:
this->copyFeatureToFramebuffer(width, featureHeight, x, y + ((offsetData.max - offsetData.min) >> 1) + 1, color);
break;
case FTGX_ALIGN_BOTTOM:
this->copyFeatureToFramebuffer(width, featureHeight, x, y - offsetData.min, color);
break;
default:
this->copyFeatureToFramebuffer(width, featureHeight, x, y + 1, color);
break;
}
}
if (format & FTGX_STYLE_STRIKE ) {
switch(format & 0x00F0) {
case FTGX_ALIGN_TOP:
this->copyFeatureToFramebuffer(width, featureHeight, x, y + ((offsetData.max + offsetData.min) >> 1), color);
break;
case FTGX_ALIGN_MIDDLE:
this->copyFeatureToFramebuffer(width, featureHeight, x, y, color);
break;
case FTGX_ALIGN_BOTTOM:
this->copyFeatureToFramebuffer(width, featureHeight, x, y - ((offsetData.max + offsetData.min) >> 1), color);
break;
default:
this->copyFeatureToFramebuffer(width, featureHeight, x, y - ((offsetData.max - offsetData.min) >> 1), color);
break;
}
}
}
/**
* Processes the supplied string and return the width of the string in pixels.
*
* This routine processes each character of the supplied text string and calculates the width of the entire string.
* Note that if precaching of the entire font set is not enabled any uncached glyph will be cached after the call to this function.
*
* @param text NULL terminated string to calculate.
* @return The width of the text string in pixels.
*/
uint16_t FreeTypeGX::getWidth(wchar_t *text) {
uint16_t strLength = wcslen(text);
uint16_t strWidth = 0;
FT_Vector pairDelta;
for (uint16_t i = 0; i < strLength; i++) {
ftgxCharData* glyphData = NULL;
if( this->fontData.find(text[i]) != this->fontData.end() ) {
glyphData = &this->fontData[text[i]];
}
else {
glyphData = this->cacheGlyphData(text[i]);
}
if(glyphData != NULL) {
if(this->ftKerningEnabled && (i > 0)) {
FT_Get_Kerning( this->ftFace, this->fontData[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta );
strWidth += pairDelta.x >> 6;
}
strWidth += glyphData->glyphAdvanceX;
}
}
return strWidth;
}
/**
*
* \overload
*/
uint16_t FreeTypeGX::getWidth(wchar_t const *text) {
return this->getWidth((wchar_t *)text);
}
/**
* Processes the supplied string and return the height of the string in pixels.
*
* This routine processes each character of the supplied text string and calculates the height of the entire string.
* Note that if precaching of the entire font set is not enabled any uncached glyph will be cached after the call to this function.
*
* @param text NULL terminated string to calculate.
* @return The height of the text string in pixels.
*/
uint16_t FreeTypeGX::getHeight(wchar_t *text) {
ftgxDataOffset offset = this->getOffset(text);
return offset.max + offset.min;
}
/**
*
* \overload
*/
uint16_t FreeTypeGX::getHeight(wchar_t const *text) {
return this->getHeight((wchar_t *)text);
}
/**
* Get the maximum offset above and minimum offset below the font origin line.
*
* This function calculates the maximum pixel height above the font origin line and the minimum
* pixel height below the font origin line and returns the values in an addressible structure.
*
* @param text NULL terminated string to calculate.
* @return The max and min values above and below the font origin line.
*/
ftgxDataOffset FreeTypeGX::getOffset(wchar_t *text) {
uint16_t strLength = wcslen(text);
uint16_t strMax = 0, strMin = 0;
for (uint16_t i = 0; i < strLength; i++) {
ftgxCharData* glyphData = NULL;
if( this->fontData.find(text[i]) != this->fontData.end() ) {
glyphData = &this->fontData[text[i]];
}
else {
glyphData = this->cacheGlyphData(text[i]);
}
if(glyphData != NULL) {
strMax = glyphData->renderOffsetMax > strMax ? glyphData->renderOffsetMax : strMax;
strMin = glyphData->renderOffsetMin > strMin ? glyphData->renderOffsetMin : strMin;
}
}
return (ftgxDataOffset){strMax, strMin};
}
/**
*
* \overload
*/
ftgxDataOffset FreeTypeGX::getOffset(wchar_t const *text) {
return this->getOffset(text);
}
/**
* Copies the supplied texture quad to the EFB.
*
* This routine uses the in-built GX quad builder functions to define the texture bounds and location on the EFB target.
*
* @param texObj A pointer to the glyph's initialized texture object.
* @param texWidth The pixel width of the texture object.
* @param texHeight The pixel height of the texture object.
* @param screenX The screen X coordinate at which to output the rendered texture.
* @param screenY The screen Y coordinate at which to output the rendered texture.
* @param color Color to apply to the texture.
*/
void FreeTypeGX::copyTextureToFramebuffer(GXTexObj *texObj, f32 texWidth, f32 texHeight, int16_t screenX, int16_t screenY, GXColor color) {
GX_LoadTexObj(texObj, GX_TEXMAP0);
GX_InvalidateTexAll();
GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE);
GX_SetVtxDesc (GX_VA_TEX0, GX_DIRECT);
GX_Begin(GX_QUADS, this->vertexIndex, 4);
GX_Position2s16(screenX, screenY);
GX_Color4u8(color.r, color.g, color.b, color.a);
GX_TexCoord2f32(0.0f, 0.0f);
GX_Position2s16(texWidth + screenX, screenY);
GX_Color4u8(color.r, color.g, color.b, color.a);
GX_TexCoord2f32(1.0f, 0.0f);
GX_Position2s16(texWidth + screenX, texHeight + screenY);
GX_Color4u8(color.r, color.g, color.b, color.a);
GX_TexCoord2f32(1.0f, 1.0f);
GX_Position2s16(screenX, texHeight + screenY);
GX_Color4u8(color.r, color.g, color.b, color.a);
GX_TexCoord2f32(0.0f, 1.0f);
GX_End();
this->setDefaultMode();
}
/**
* Creates a feature quad to the EFB.
*
* This function creates a simple quad for displaying underline or strikeout text styling.
*
* @param featureWidth The pixel width of the quad.
* @param featureHeight The pixel height of the quad.
* @param screenX The screen X coordinate at which to output the quad.
* @param screenY The screen Y coordinate at which to output the quad.
* @param color Color to apply to the texture.
*/
void FreeTypeGX::copyFeatureToFramebuffer(f32 featureWidth, f32 featureHeight, int16_t screenX, int16_t screenY, GXColor color) {
GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR);
GX_SetVtxDesc (GX_VA_TEX0, GX_NONE);
GX_Begin(GX_QUADS, this->vertexIndex, 4);
GX_Position2s16(screenX, screenY);
GX_Color4u8(color.r, color.g, color.b, color.a);
GX_Position2s16(featureWidth + screenX, screenY);
GX_Color4u8(color.r, color.g, color.b, color.a);
GX_Position2s16(featureWidth + screenX, featureHeight + screenY);
GX_Color4u8(color.r, color.g, color.b, color.a);
GX_Position2s16(screenX, featureHeight + screenY);
GX_Color4u8(color.r, color.g, color.b, color.a);
GX_End();
this->setDefaultMode();
}

View File

@ -1,286 +0,0 @@
/*
* FreeTypeGX is a wrapper class for libFreeType which renders a compiled
* FreeType parsable font into a GX texture for Wii homebrew development.
* Copyright (C) 2008 Armin Tamzarian
* Modified by Tantric, 2009
*
* This file is part of FreeTypeGX.
*
* FreeTypeGX is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FreeTypeGX 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FreeTypeGX. If not, see <http://www.gnu.org/licenses/>.
*/
/** \mainpage FreeTypeGX
*
* \section sec_intro Introduction
*
* FreeTypeGX is a wrapper class for libFreeType which renders a compiled FreeType parsable font into a GX texture for Wii homebrew development.
* <br>
* FreeTypeGX is written in C++ and makes use of a selectable pre-buffered or buffer-on-demand methodology to allow fast and efficient printing of text to the EFB.
* <p>
* This library was developed in-full by Armin Tamzarian with the support of developers in \#wiibrew on EFnet.
*
* \section sec_installation_source Installation (Source Code)
*
* -# Ensure that you have the <a href = "http://www.tehskeen.com/forums/showthread.php?t=9404">libFreeType</a> Wii library installed in your development environment with the library added to your Makefile where appropriate.
* -# Ensure that you have the <a href = "http://code.google.com/p/metaphrasis">Metaphrasis</a> library installed in your development environment with the library added to your Makefile where appropriate.
* -# Extract the FreeTypeGX archive.
* -# Copy the contents of the <i>src</i> directory into your project's development path.
* -# Include the FreeTypeGX header file in your code using syntax such as the following:
* \code
* #include "FreeTypeGX.h"
* \endcode
*
* \section sec_installation_library Installation (Library)
*
* -# Ensure that you have the <a href = "http://www.tehskeen.com/forums/showthread.php?t=9404">libFreeType</a> Wii library installed in your development environment with the library added to your Makefile where appropriate.
* -# Ensure that you have the <a href = "http://code.google.com/p/metaphrasis">Metaphrasis</a> library installed in your development environment with the library added to your Makefile where appropriate.
* -# Extract the FreeTypeGX archive.
* -# Copy the contents of the <i>lib</i> directory into your <i>devKitPro/libogc</i> directory.
* -# Include the FreeTypeGX header file in your code using syntax such as the following:
* \code
* #include "FreeTypeGX.h"
* \endcode
*
* \section sec_freetypegx_prerequisites FreeTypeGX Prerequisites
*
* Before you begin using FreeTypeGX in your project you must ensure that the desired font in compiled into your project. For this example I will assume you are building your project with a Makefile using devKitPro evironment and are attempting to include a font whose filename is rursus_compact_mono.ttf.
*
* -# Copy the font into a directory which will be processed by the project's Makefile. If you are unsure about where you should place your font just copy the it into your project's source directory.
* \n\n
* -# Modify the Makefile to convert the font into an object file:
* \code
* %.ttf.o : %.ttf
* @echo $(notdir $<)
* $(bin2o)
* \endcode
* \n
* -# Include the font object's generated header file in your source code:
* \code
* #include "rursus_compact_mono_ttf.h"
* \endcode
* This header file defines the two variables that you will need for use within your project:
* \code
* extern const u8 rursus_compact_mono_ttf[]; A pointer to the font buffer within the compiled project.
* extern const u32 rursus_compact_mono_ttf_size; The size of the font's buffer in bytes.
* \endcode
*
* \section sec_freetypegx_usage FreeTypeGX Usage
*
* -# Within the file you included the FreeTypeGX.h header create an instance object of the FreeTypeGX class:
* \code
* FreeTypeGX *freeTypeGX = new FreeTypeGX();
* \endcode
* Alternately you can specify a texture format to which you would like to render the font characters. Note that the default value for this parameter is GX_TF_RGBA8.
* \code
* FreeTypeGX *freeTypeGX = new FreeTypeGX(GX_TF_RGB565);
* \endcode
* Furthermore, you can also specify a vertex format index to avoid conflicts with concurrent libraries or other systems. Note that the default value for this parameter is GX_VTXFMT1.
* \code
* FreeTypeGX *freeTypeGX = new FreeTypeGX(GX_TF_RGB565, GX_VTXFMT1);
* \endcode
* \n
* Currently supported textures are:
* \li <i>GX_TF_I4</i>
* \li <i>GX_TF_I8</i>
* \li <i>GX_TF_IA4</i>
* \li <i>GX_TF_IA8</i>
* \li <i>GX_TF_RGB565</i>
* \li <i>GX_TF_RGB5A3</i>
* \li <i>GX_TF_RGBA8</i>
*
* \n
* -# Using the allocated FreeTypeGX instance object call the loadFont function to load the font from the compiled buffer and specify the desired point size. Note that this function can be called multiple times to load a new:
* \code
* freeTypeGX->loadFont(rursus_compact_mono_ttf, rursus_compact_mono_ttf_size, 64);
* \endcode
* Alternately you can specify a flag which will load and cache all available font glyphs immidiately. Note that on large font sets enabling this feature could take a significant amount of time.
* \code
* freeTypeGX->loadFont(rursus_compact_mono_ttf, rursus_compact_mono_ttf_size, 64, true);
* \endcode
* \n
* -# If necessary you can enable compatibility modes with concurrent libraries or systems. For more information on this feature see the documentation for setCompatibilityMode:
* \code
* freeTypeGX->setCompatibilityMode(FTGX_COMPATIBILITY_GRRLIB);
* \endcode
* -# Using the allocated FreeTypeGX instance object call the drawText function to print a string at the specified screen X and Y coordinates to the current EFB:
* \code
* freeTypeGX->drawText(10, 25, _TEXT("FreeTypeGX Rocks!"));
* \endcode
* Alternately you can specify a <i>GXColor</i> object you would like to apply to the printed characters:
* \code
* freeTypeGX->drawText(10, 25, _TEXT("FreeTypeGX Rocks!"),
* (GXColor){0xff, 0xee, 0xaa, 0xff});
* \endcode
* Furthermore you can also specify a group of styling parameters which will modify the positioning or style of the text:
* \code
* freeTypeGX->drawText(10, 25, _TEXT("FreeTypeGX Rocks!"),
* (GXColor){0xff, 0xee, 0xaa, 0xff},
* FTGX_JUSTIFY_CENTER | FTGX_ALIGN_BOTTOM | FTGX_STYLE_UNDERLINE);
* \endcode
* \n
* Currently style parameters are:
* \li <i>FTGX_JUSTIFY_LEFT</i>
* \li <i>FTGX_JUSTIFY_CENTER</i>
* \li <i>FTGX_JUSTIFY_RIGHT</i>
* \li <i>FTGX_ALIGN_TOP</i>
* \li <i>FTGX_ALIGN_MIDDLE</i>
* \li <i>FTGX_ALIGN_BOTTOM</i>
* \li <i>FTGX_STYLE_UNDERLINE</i>
* \li <i>FTGX_STYLE_STRIKE</i>
*
* \section sec_license License
*
* FreeTypeGX is distributed under the GNU Lesser General Public License.
*
* \section sec_contact Contact
*
* If you have any suggestions, questions, or comments regarding this library feel free to e-mail me at tamzarian1989 [at] gmail [dawt] com.
*/
#ifndef FREETYPEGX_H_
#define FREETYPEGX_H_
#include <gccore.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_BITMAP_H
#include <Metaphrasis.h>
#include <malloc.h>
#include <string.h>
#include <map>
/*! \struct ftgxCharData_
*
* Font face character glyph relevant data structure.
*/
typedef struct ftgxCharData_ {
uint16_t glyphAdvanceX; /**< Character glyph X coordinate advance in pixels. */
uint16_t glyphIndex; /**< Charachter glyph index in the font face. */
uint16_t textureWidth; /**< Texture width in pixels/bytes. */
uint16_t textureHeight; /**< Texture glyph height in pixels/bytes. */
uint16_t renderOffsetY; /**< Texture Y axis bearing offset. */
uint16_t renderOffsetMax; /**< Texture Y axis bearing maximum value. */
uint16_t renderOffsetMin; /**< Texture Y axis bearing minimum value. */
uint32_t* glyphDataTexture; /**< Glyph texture bitmap data buffer. */
} ftgxCharData;
/*! \struct ftgxDataOffset_
*
* Offset structure which hold both a maximum and minimum value.
*/
typedef struct ftgxDataOffset_ {
int16_t max; /**< Maximum data offset. */
int16_t min; /**< Minimum data offset. */
} ftgxDataOffset;
#define _TEXT(t) L ## t /**< Unicode helper macro. */
#define FTGX_NULL 0x0000
#define FTGX_JUSTIFY_LEFT 0x0001
#define FTGX_JUSTIFY_CENTER 0x0002
#define FTGX_JUSTIFY_RIGHT 0x0004
#define FTGX_ALIGN_TOP 0x0010
#define FTGX_ALIGN_MIDDLE 0x0020
#define FTGX_ALIGN_BOTTOM 0x0040
#define FTGX_STYLE_UNDERLINE 0x0100
#define FTGX_STYLE_STRIKE 0x0200
#define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_MODULATE 0X0001
#define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_DECAL 0X0002
#define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_BLEND 0X0004
#define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_REPLACE 0X0008
#define FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_PASSCLR 0X0010
#define FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_NONE 0X0100
#define FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_DIRECT 0X0200
#define FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_INDEX8 0X0400
#define FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_INDEX16 0X0800
#define FTGX_COMPATIBILITY_NONE 0x0000
#define FTGX_COMPATIBILITY_GRRLIB FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_PASSCLR | FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_NONE
#define FTGX_COMPATIBILITY_LIBWIISPRITE FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_MODULATE | FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_DIRECT
const GXColor ftgxWhite = (GXColor){0xff, 0xff, 0xff, 0xff}; /**< Constant color value used only to sanitize Doxygen documentation. */
/*! \class FreeTypeGX
* \brief Wrapper class for the libFreeType library with GX rendering.
* \author Armin Tamzarian
* \version 0.2.4
*
* FreeTypeGX acts as a wrapper class for the libFreeType library. It supports precaching of transformed glyph data into
* a specified texture format. Rendering of the data to the EFB is accomplished through the application of high performance
* GX texture functions resulting in high throughput of string rendering.
*/
class FreeTypeGX {
private:
FT_Library ftLibrary; /**< FreeType FT_Library instance. */
FT_Face ftFace; /**< FreeType reusable FT_Face typographic object. */
FT_GlyphSlot ftSlot; /**< FreeType reusable FT_GlyphSlot glyph container object. */
FT_UInt ftPointSize; /**< Requested size of the rendered font. */
bool ftKerningEnabled; /**< Flag indicating the availability of font kerning data. */
uint8_t textureFormat; /**< Defined texture format of the target EFB. */
uint8_t vertexIndex; /**< Vertex format descriptor index. */
uint32_t compatibilityMode; /**< Compatibility mode for default tev operations and vertex descriptors. */
std::map<wchar_t, ftgxCharData> fontData; /**< Map which holds the glyph data structures for the corresponding characters. */
static uint16_t adjustTextureWidth(uint16_t textureWidth, uint8_t textureFormat);
static uint16_t adjustTextureHeight(uint16_t textureHeight, uint8_t textureFormat);
static uint16_t getStyleOffsetWidth(uint16_t width, uint16_t format);
static uint16_t getStyleOffsetHeight(ftgxDataOffset offset, uint16_t format);
void unloadFont();
ftgxCharData *cacheGlyphData(wchar_t charCode);
uint16_t cacheGlyphDataComplete();
void loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData);
void setDefaultMode();
void drawTextFeature(int16_t x, int16_t y, uint16_t width, ftgxDataOffset offsetData, uint16_t format, GXColor color);
void copyTextureToFramebuffer(GXTexObj *texObj, f32 texWidth, f32 texHeight, int16_t screenX, int16_t screenY, GXColor color);
void copyFeatureToFramebuffer(f32 featureWidth, f32 featureHeight, int16_t screenX, int16_t screenY, GXColor color);
public:
FreeTypeGX(uint8_t textureFormat = GX_TF_RGBA8, uint8_t vertexIndex = GX_VTXFMT1);
~FreeTypeGX();
static wchar_t* charToWideChar(char* p);
static wchar_t* charToWideChar(const char* p);
void setVertexFormat(uint8_t vertexIndex);
void setCompatibilityMode(uint32_t compatibilityMode);
uint16_t loadFont(uint8_t* fontBuffer, FT_Long bufferSize, FT_UInt pointSize, bool cacheAll = false);
uint16_t loadFont(const uint8_t* fontBuffer, FT_Long bufferSize, FT_UInt pointSize, bool cacheAll = false);
void changeSize(FT_UInt pointSize);
uint16_t drawText(int16_t x, int16_t y, wchar_t *text, GXColor color = ftgxWhite, uint16_t textStyling = FTGX_NULL);
uint16_t drawText(int16_t x, int16_t y, wchar_t const *text, GXColor color = ftgxWhite, uint16_t textStyling = FTGX_NULL);
uint16_t getWidth(wchar_t *text);
uint16_t getWidth(wchar_t const *text);
uint16_t getHeight(wchar_t *text);
uint16_t getHeight(wchar_t const *text);
ftgxDataOffset getOffset(wchar_t *text);
ftgxDataOffset getOffset(wchar_t const *text);
};
#endif /* FREETYPEGX_H_ */

View File

@ -9,11 +9,9 @@
***************************************************************************/ ***************************************************************************/
#include <gccore.h> #include <gccore.h>
#include <ogcsys.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <asndlib.h>
#include "audio.h" #include "audio.h"
@ -92,34 +90,6 @@ void SetAudioRate(int type)
gameType = type; gameType = type;
} }
/****************************************************************************
* SwitchAudioMode
*
* Switches between menu sound and emulator sound
***************************************************************************/
void
SwitchAudioMode(int mode)
{
if(mode == 0) // emulator
{
#ifndef NO_SOUND
ASND_Pause(1);
ASND_End();
#endif
AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
AUDIO_RegisterDMACallback(AudioPlayer);
}
else // menu
{
AUDIO_StopDMA();
AUDIO_RegisterDMACallback(NULL);
#ifndef NO_SOUND
ASND_Init();
ASND_Pause(0);
#endif
}
}
/**************************************************************************** /****************************************************************************
* InitialiseSound * InitialiseSound
***************************************************************************/ ***************************************************************************/
@ -127,22 +97,8 @@ SwitchAudioMode(int mode)
void InitialiseSound() void InitialiseSound()
{ {
AUDIO_Init(NULL); // Start audio subsystem AUDIO_Init(NULL); // Start audio subsystem
} AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
AUDIO_RegisterDMACallback(AudioPlayer);
/****************************************************************************
* ShutdownAudio
*
* Shuts down audio subsystem. Useful to avoid unpleasant sounds if a
* crash occurs during shutdown.
***************************************************************************/
void ShutdownAudio()
{
#ifndef NO_SOUND
ASND_Pause(1);
ASND_End();
#endif
AUDIO_StopDMA();
AUDIO_RegisterDMACallback(NULL);
} }
/**************************************************************************** /****************************************************************************

View File

@ -16,8 +16,6 @@
void InitialiseSound(); void InitialiseSound();
void StopAudio(); void StopAudio();
void SetAudioRate(int type); void SetAudioRate(int type);
void SwitchAudioMode(int mode);
void ShutdownAudio();
class SoundWii: public SoundDriver class SoundWii: public SoundDriver
{ {

View File

@ -25,50 +25,6 @@
***************************************************************************/ ***************************************************************************/
CtrlrMap ctrlr_def[5] = { CtrlrMap ctrlr_def[5] = {
// Gamecube controller btn def
{
CTRLR_GCPAD,
13,
{
{PAD_BUTTON_DOWN, "DOWN"},
{PAD_BUTTON_UP, "UP"},
{PAD_BUTTON_LEFT, "LEFT"},
{PAD_BUTTON_RIGHT, "RIGHT"},
{PAD_BUTTON_A, "A"},
{PAD_BUTTON_B, "B"},
{PAD_BUTTON_X, "X"},
{PAD_BUTTON_Y, "Y"},
{PAD_BUTTON_MENU, "START"},
{PAD_BUTTON_START, "START"},
{PAD_TRIGGER_L, "L"},
{PAD_TRIGGER_R, "R"},
{PAD_TRIGGER_Z, "Z"},
{0, ""},
{0, ""}
}
},
// Wiimote btn def
{
CTRLR_WIIMOTE,
11,
{
{WPAD_BUTTON_DOWN, "DOWN"},
{WPAD_BUTTON_UP, "UP"},
{WPAD_BUTTON_LEFT, "LEFT"},
{WPAD_BUTTON_RIGHT, "RIGHT"},
{WPAD_BUTTON_A, "A"},
{WPAD_BUTTON_B, "B"},
{WPAD_BUTTON_1, "1"},
{WPAD_BUTTON_2, "2"},
{WPAD_BUTTON_PLUS, "PLUS"},
{WPAD_BUTTON_MINUS, "MINUS"},
{WPAD_BUTTON_HOME, "HOME"},
{0, ""},
{0, ""},
{0, ""},
{0, ""}
}
},
// Nunchuk btn def // Nunchuk btn def
{ {
CTRLR_NUNCHUK, CTRLR_NUNCHUK,
@ -107,12 +63,56 @@ CtrlrMap ctrlr_def[5] = {
{WPAD_CLASSIC_BUTTON_PLUS, "PLUS"}, {WPAD_CLASSIC_BUTTON_PLUS, "PLUS"},
{WPAD_CLASSIC_BUTTON_MINUS, "MINUS"}, {WPAD_CLASSIC_BUTTON_MINUS, "MINUS"},
{WPAD_CLASSIC_BUTTON_HOME, "HOME"}, {WPAD_CLASSIC_BUTTON_HOME, "HOME"},
{WPAD_CLASSIC_BUTTON_FULL_L, "L"}, {WPAD_CLASSIC_BUTTON_FULL_L, "L TRIG"},
{WPAD_CLASSIC_BUTTON_FULL_R, "R"}, {WPAD_CLASSIC_BUTTON_FULL_R, "R TRIG"},
{WPAD_CLASSIC_BUTTON_ZL, "ZL"}, {WPAD_CLASSIC_BUTTON_ZL, "ZL"},
{WPAD_CLASSIC_BUTTON_ZR, "ZR"} {WPAD_CLASSIC_BUTTON_ZR, "ZR"}
} }
}, },
// Gamecube controller btn def
{
CTRLR_GCPAD,
13,
{
{PAD_BUTTON_DOWN, "DOWN"},
{PAD_BUTTON_UP, "UP"},
{PAD_BUTTON_LEFT, "LEFT"},
{PAD_BUTTON_RIGHT, "RIGHT"},
{PAD_BUTTON_A, "A"},
{PAD_BUTTON_B, "B"},
{PAD_BUTTON_X, "X"},
{PAD_BUTTON_Y, "Y"},
{PAD_BUTTON_MENU, "MENU"},
{PAD_BUTTON_START, "START"},
{PAD_TRIGGER_L, "L TRIG"},
{PAD_TRIGGER_R, "R TRIG"},
{PAD_TRIGGER_Z, "Z"},
{0, ""},
{0, ""}
}
},
// Wiimote btn def
{
CTRLR_WIIMOTE,
11,
{
{WPAD_BUTTON_DOWN, "DOWN"},
{WPAD_BUTTON_UP, "UP"},
{WPAD_BUTTON_LEFT, "LEFT"},
{WPAD_BUTTON_RIGHT, "RIGHT"},
{WPAD_BUTTON_A, "A"},
{WPAD_BUTTON_B, "B"},
{WPAD_BUTTON_1, "1"},
{WPAD_BUTTON_2, "2"},
{WPAD_BUTTON_PLUS, "PLUS"},
{WPAD_BUTTON_MINUS, "MINUS"},
{WPAD_BUTTON_HOME, "HOME"},
{0, ""},
{0, ""},
{0, ""},
{0, ""}
}
},
// Keyboard btn def, see http://www.usb.org/developers/devclass_docs/Hut1_12.pdf // Keyboard btn def, see http://www.usb.org/developers/devclass_docs/Hut1_12.pdf
{ {
CTRLR_KEYBOARD, CTRLR_KEYBOARD,
@ -250,7 +250,9 @@ CtrlrMap ctrlr_def[5] = {
{231, "RWIN"}, {231, "RWIN"},
{232, "MOUSEL"}, {232, "MOUSEL"},
{233, "MOUSER"}, {233, "MOUSER"},
{234, "MOUSEM"} {234, "MOUSEM"},
} }
} }
}; };

View File

@ -13,16 +13,14 @@
enum { enum {
CTRLR_NONE = -1, CTRLR_NONE = -1,
CTRLR_GCPAD,
CTRLR_WIIMOTE,
CTRLR_NUNCHUK, CTRLR_NUNCHUK,
CTRLR_CLASSIC, CTRLR_CLASSIC,
CTRLR_KEYBOARD CTRLR_GCPAD,
CTRLR_WIIMOTE,
CTRLR_KEYBOARD,
CTRLR_SNES = 7 // give some other value for the snes padmap
}; };
const char ctrlrName[4][20] =
{ "GameCube Controller", "Wiimote", "Nunchuk + Wiimote", "Classic Controller" };
typedef struct _btn_map { typedef struct _btn_map {
u32 btn; // button 'id' u32 btn; // button 'id'
char* name; // button name char* name; // button name

View File

@ -21,11 +21,10 @@ extern "C" {
} }
#endif #endif
#include "vba.h" #include "menudraw.h"
#include "menu.h"
#include "gcunzip.h" #include "gcunzip.h"
#include "filebrowser.h" #include "filesel.h"
#include "fileop.h" #include "vba.h"
#define MAXDVDFILES 2000 #define MAXDVDFILES 2000
@ -142,6 +141,7 @@ static int dvd_buffered_read(void *dst, u32 len, u64 offset)
* This function relies on dvddir (file offset) being prepopulated! * This function relies on dvddir (file offset) being prepopulated!
* returns: 1 - ok ; 0 - error * returns: 1 - ok ; 0 - error
***************************************************************************/ ***************************************************************************/
int dvd_safe_read(void *dst_v, u32 len, u64 fileoffset) int dvd_safe_read(void *dst_v, u32 len, u64 fileoffset)
{ {
u64 offset = dvddir + fileoffset; u64 offset = dvddir + fileoffset;
@ -318,40 +318,35 @@ getpvd ()
* *
* Tests if a ISO9660 DVD is inserted and available, and mounts it * Tests if a ISO9660 DVD is inserted and available, and mounts it
***************************************************************************/ ***************************************************************************/
bool MountDVD(bool silent) bool MountDVD(bool silent)
{ {
bool res = false; if (!getpvd())
if (getpvd())
{
return true;
}
else
{ {
ShowAction("Loading DVD..."); ShowAction("Loading DVD...");
#ifdef HW_DOL #ifdef HW_DOL
DVD_Mount(); // mount the DVD unit again DVD_Mount(); // mount the DVD unit again
#else #elif HW_RVL
u32 val; u32 val;
DI_GetCoverRegister(&val); DI_GetCoverRegister(&val);
if(val & 0x1) // True if no disc inside, use (val & 0x2) for true if disc inside. if(val & 0x1) // True if no disc inside, use (val & 0x2) for true if disc inside.
{ {
if(!silent) if(!silent)
ErrorPrompt("No disc inserted!"); WaitPrompt("No disc inserted!");
CancelAction();
return false; return false;
} }
DI_Mount(); DI_Mount();
while(DI_GetStatus() & DVD_INIT) usleep(20000); while(DI_GetStatus() & DVD_INIT);
#endif #endif
if (getpvd()) if (!getpvd())
res = true; {
else if(!silent) if(!silent)
ErrorPrompt("Invalid DVD."); WaitPrompt ("Invalid DVD.");
return false;
}
} }
CancelAction(); return true;
return res;
} }
/**************************************************************************** /****************************************************************************
@ -360,6 +355,7 @@ bool MountDVD(bool silent)
* Support function to return the next file entry, if any * Support function to return the next file entry, if any
* Declared static to avoid accidental external entry. * Declared static to avoid accidental external entry.
***************************************************************************/ ***************************************************************************/
static int static int
getentry (int entrycount, unsigned char dvdbuffer[]) getentry (int entrycount, unsigned char dvdbuffer[])
{ {
@ -449,7 +445,7 @@ getentry (int entrycount, unsigned char dvdbuffer[])
if(!newBrowserList) // failed to allocate required memory if(!newBrowserList) // failed to allocate required memory
{ {
ResetBrowser(); ResetBrowser();
ErrorPrompt("Out of memory: too many files!"); WaitPrompt("Out of memory: too many files!");
return 0; return 0;
} }
else else
@ -459,16 +455,8 @@ getentry (int entrycount, unsigned char dvdbuffer[])
memset(&(browserList[entrycount]), 0, sizeof(BROWSERENTRY)); // clear the new entry memset(&(browserList[entrycount]), 0, sizeof(BROWSERENTRY)); // clear the new entry
strncpy (browserList[entrycount].filename, fname, MAXJOLIET); strncpy (browserList[entrycount].filename, fname, MAXJOLIET);
StripExt(tmpname, fname); // hide file extension
if(strcmp(fname,"..") == 0) strncpy (browserList[entrycount].displayname, tmpname, MAXDISPLAY);
{
sprintf(browserList[entrycount].displayname, "Up One Level");
}
else
{
StripExt(tmpname, fname); // hide file extension
strncpy (browserList[entrycount].displayname, tmpname, MAXDISPLAY);
}
memcpy (&offset32, &dvdbuffer[diroffset + EXTENT], 4); memcpy (&offset32, &dvdbuffer[diroffset + EXTENT], 4);
@ -495,7 +483,7 @@ getentry (int entrycount, unsigned char dvdbuffer[])
* It relies on dvddir and dvddirlength being pre-populated by a call to * It relies on dvddir and dvddirlength being pre-populated by a call to
* getpvd, a previous parse or a menu selection. * getpvd, a previous parse or a menu selection.
* *
* The return value is number of files collected, or -1 on failure. * The return value is number of files collected, or 0 on failure.
***************************************************************************/ ***************************************************************************/
int int
ParseDVDdirectory () ParseDVDdirectory ()
@ -518,7 +506,7 @@ ParseDVDdirectory ()
while (len < pdlength) while (len < pdlength)
{ {
if (dvd_read (&dvdbuffer, 2048, pdoffset) == 0) if (dvd_read (&dvdbuffer, 2048, pdoffset) == 0)
return -1; return 0;
diroffset = 0; diroffset = 0;
@ -535,7 +523,6 @@ ParseDVDdirectory ()
// Sort the file list // Sort the file list
qsort(browserList, filecount, sizeof(BROWSERENTRY), FileSortCallback); qsort(browserList, filecount, sizeof(BROWSERENTRY), FileSortCallback);
browser.numEntries = filecount;
return filecount; return filecount;
} }
@ -543,6 +530,7 @@ ParseDVDdirectory ()
* SetDVDdirectory * SetDVDdirectory
* Set the current DVD file offset * Set the current DVD file offset
***************************************************************************/ ***************************************************************************/
void SetDVDdirectory(u64 dir, int length) void SetDVDdirectory(u64 dir, int length)
{ {
dvddir = dir; dvddir = dir;
@ -591,18 +579,12 @@ static bool SwitchDVDFolderR(char * dir, int maxDepth)
if(dirindex >= 0) if(dirindex >= 0)
{ {
dvddir = browserList[dirindex].offset;
dvddirlength = browserList[dirindex].length;
browser.selIndex = dirindex; browser.selIndex = dirindex;
if(browserList[dirindex].isdir) // only parse directories if(browserList[dirindex].isdir) // only parse directories
{ browser.numEntries = ParseDVDdirectory();
UpdateDirName(METHOD_DVD);
ParseDVDdirectory();
}
else
{
dvddir = browserList[dirindex].offset;
dvddirlength = browserList[dirindex].length;
}
if(lastdir) if(lastdir)
return true; return true;
@ -615,8 +597,8 @@ static bool SwitchDVDFolderR(char * dir, int maxDepth)
bool SwitchDVDFolder(char origdir[]) bool SwitchDVDFolder(char origdir[])
{ {
// make a copy of origdir so we don't mess with original // make a copy of origdir so we don't mess with original
char dir[1024]; char dir[200];
strncpy(dir, origdir, 1024); strcpy(dir, origdir);
char * dirptr = dir; char * dirptr = dir;
@ -630,7 +612,6 @@ bool SwitchDVDFolder(char origdir[])
// start searching at root of DVD // start searching at root of DVD
dvddir = dvdrootdir; dvddir = dvdrootdir;
dvddirlength = dvdrootlength; dvddirlength = dvdrootlength;
browser.dir[0] = 0;
ParseDVDdirectory(); ParseDVDdirectory();
return SwitchDVDFolderR(dirptr, 0); return SwitchDVDFolderR(dirptr, 0);
@ -641,10 +622,10 @@ bool SwitchDVDFolder(char origdir[])
* This function will load a file from DVD * This function will load a file from DVD
* It assumes dvddir and dvddirlength are prepopulated * It assumes dvddir and dvddirlength are prepopulated
***************************************************************************/ ***************************************************************************/
int int
LoadDVDFileOffset (unsigned char *buffer, int length) LoadDVDFileOffset (unsigned char *buffer, int length)
{ {
int result = 0;
int offset; int offset;
int blocks; int blocks;
int i; int i;
@ -662,19 +643,17 @@ LoadDVDFileOffset (unsigned char *buffer, int length)
{ {
ret = dvd_read (buffer, length, discoffset); ret = dvd_read (buffer, length, discoffset);
if(ret <= 0) // read failure if(ret <= 0) // read failure
goto done; return 0;
else
result = length;
} }
else // load whole file else // load whole file
{ {
ret = dvd_read (readbuffer, 2048, discoffset); ret = dvd_read (readbuffer, 2048, discoffset);
if(ret <= 0) // read failure if(ret <= 0) // read failure
goto done; return 0;
if (IsZipFile (readbuffer)) if (IsZipFile (readbuffer))
{ {
result = UnZipBuffer (buffer, METHOD_DVD); // unzip from dvd return UnZipBuffer (buffer, METHOD_DVD); // unzip from dvd
} }
else else
{ {
@ -682,7 +661,7 @@ LoadDVDFileOffset (unsigned char *buffer, int length)
{ {
ret = dvd_read (readbuffer, 2048, discoffset); ret = dvd_read (readbuffer, 2048, discoffset);
if(ret <= 0) // read failure if(ret <= 0) // read failure
goto done; return 0;
memcpy (buffer + offset, readbuffer, 2048); memcpy (buffer + offset, readbuffer, 2048);
offset += 2048; offset += 2048;
discoffset += 2048; discoffset += 2048;
@ -695,15 +674,12 @@ LoadDVDFileOffset (unsigned char *buffer, int length)
i = dvddirlength % 2048; i = dvddirlength % 2048;
ret = dvd_read (readbuffer, 2048, discoffset); ret = dvd_read (readbuffer, 2048, discoffset);
if(ret <= 0) // read failure if(ret <= 0) // read failure
goto done; return 0;
memcpy (buffer + offset, readbuffer, i); memcpy (buffer + offset, readbuffer, i);
} }
result = dvddirlength;
} }
} }
done: return dvddirlength;
CancelAction();
return result;
} }
/**************************************************************************** /****************************************************************************
@ -712,30 +688,20 @@ done:
* It will attempt to find the offset of the file, and if successful it * It will attempt to find the offset of the file, and if successful it
* will populate dvddir and dvddirlength, and load the file * will populate dvddir and dvddirlength, and load the file
***************************************************************************/ ***************************************************************************/
int int
LoadDVDFile(char * buffer, char *filepath, int datasize, bool silent) LoadDVDFile(char * buffer, char *filepath, int datasize, bool silent)
{ {
int ret = 0;
// retain original browser information
char origDir[MAXPATHLEN];
memset(origDir, 0, MAXPATHLEN);
strncpy(origDir, browser.dir, MAXPATHLEN);
int origSelIndex = browser.selIndex;
int origPageIndex = browser.selIndex;
if(SwitchDVDFolder(filepath)) if(SwitchDVDFolder(filepath))
ret = LoadDVDFileOffset ((unsigned char *)buffer, datasize); {
else if(!silent) return LoadDVDFileOffset ((unsigned char *)buffer, datasize);
ErrorPrompt("Error loading file!"); }
else
// restore browser information {
memset(browser.dir, 0, MAXPATHLEN); if(!silent)
strncpy(browser.dir, origDir, MAXPATHLEN); WaitPrompt("Error loading file!");
browser.selIndex = origSelIndex; return 0;
browser.pageIndex = origPageIndex; }
return ret;
} }
/**************************************************************************** /****************************************************************************
@ -802,8 +768,8 @@ int dvd_driveid()
dvd[6] = 0x20; dvd[6] = 0x20;
dvd[7] = 3; dvd[7] = 3;
while( dvd[7] & 1 ); while( dvd[7] & 1 )
;
DCFlushRange((void *)0x80000000, 32); DCFlushRange((void *)0x80000000, 32);
return (int)inquiry[2]; return (int)inquiry[2];

View File

@ -1,538 +0,0 @@
/****************************************************************************
* Visual Boy Advance GX
*
* Tantric September 2008
*
* filebrowser.cpp
*
* Generic file routines - reading, writing, browsing
***************************************************************************/
#include <gccore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wiiuse/wpad.h>
#include <sys/dir.h>
#include <malloc.h>
#ifdef HW_RVL
extern "C" {
#include <di/di.h>
}
#endif
#include "vba.h"
#include "dvd.h"
#include "vbasupport.h"
#include "vmmem.h"
#include "filebrowser.h"
#include "menu.h"
#include "video.h"
#include "networkop.h"
#include "fileop.h"
#include "memcardop.h"
#include "input.h"
#include "gcunzip.h"
#include "wiiusbsupport.h"
BROWSERINFO browser;
BROWSERENTRY * browserList = NULL; // list of files/folders in browser
char rootdir[10];
char szpath[MAXPATHLEN];
bool inSz = false;
char ROMFilename[512];
bool ROMLoaded = false;
/****************************************************************************
* autoLoadMethod()
* Auto-determines and sets the load method
* Returns method set
****************************************************************************/
int autoLoadMethod()
{
ShowAction ("Attempting to determine load method...");
int method = METHOD_AUTO;
if(ChangeInterface(METHOD_SD, SILENT))
method = METHOD_SD;
else if(ChangeInterface(METHOD_USB, SILENT))
method = METHOD_USB;
else if(ChangeInterface(METHOD_DVD, SILENT))
method = METHOD_DVD;
else if(ChangeInterface(METHOD_SMB, SILENT))
method = METHOD_SMB;
else
ErrorPrompt("Unable to auto-determine load method!");
if(GCSettings.LoadMethod == METHOD_AUTO)
GCSettings.LoadMethod = method; // save method found for later use
CancelAction();
return method;
}
/****************************************************************************
* autoSaveMethod()
* Auto-determines and sets the save method
* Returns method set
****************************************************************************/
int autoSaveMethod(bool silent)
{
if(!silent)
ShowAction ("Attempting to determine save method...");
int method = METHOD_AUTO;
if(ChangeInterface(METHOD_SD, SILENT))
method = METHOD_SD;
else if(ChangeInterface(METHOD_USB, SILENT))
method = METHOD_USB;
else if(ChangeInterface(METHOD_MC_SLOTA, SILENT))
method = METHOD_MC_SLOTA;
else if(ChangeInterface(METHOD_MC_SLOTB, SILENT))
method = METHOD_MC_SLOTB;
else if(ChangeInterface(METHOD_SMB, SILENT))
method = METHOD_SMB;
else if(!silent)
ErrorPrompt("Unable to auto-determine save method!");
if(GCSettings.SaveMethod == METHOD_AUTO)
GCSettings.SaveMethod = method; // save method found for later use
CancelAction();
return method;
}
/****************************************************************************
* ResetBrowser()
* Clears the file browser memory, and allocates one initial entry
***************************************************************************/
void ResetBrowser()
{
browser.numEntries = 0;
browser.selIndex = 0;
browser.pageIndex = 0;
// Clear any existing values
if(browserList != NULL)
{
free(browserList);
browserList = NULL;
}
// set aside space for 1 entry
browserList = (BROWSERENTRY *)malloc(sizeof(BROWSERENTRY));
memset(browserList, 0, sizeof(BROWSERENTRY));
}
/****************************************************************************
* UpdateDirName()
* Update curent directory name for file browser
***************************************************************************/
int UpdateDirName(int method)
{
int size=0;
char * test;
char temp[1024];
// update DVD directory
if(method == METHOD_DVD)
SetDVDdirectory(browserList[browser.selIndex].offset, browserList[browser.selIndex].length);
/* current directory doesn't change */
if (strcmp(browserList[browser.selIndex].filename,".") == 0)
{
return 0;
}
/* go up to parent directory */
else if (strcmp(browserList[browser.selIndex].filename,"..") == 0)
{
/* determine last subdirectory namelength */
sprintf(temp,"%s",browser.dir);
test = strtok(temp,"/");
while (test != NULL)
{
size = strlen(test);
test = strtok(NULL,"/");
}
/* remove last subdirectory name */
size = strlen(browser.dir) - size - 1;
browser.dir[size] = 0;
return 1;
}
/* Open a directory */
else
{
/* test new directory namelength */
if ((strlen(browser.dir)+1+strlen(browserList[browser.selIndex].filename)) < MAXPATHLEN)
{
/* update current directory name */
sprintf(browser.dir, "%s/%s",browser.dir, browserList[browser.selIndex].filename);
return 1;
}
else
{
ErrorPrompt("Directory name is too long!");
return -1;
}
}
}
bool MakeFilePath(char filepath[], int type, int method, char * filename, int filenum)
{
char file[512];
char folder[1024];
char ext[4];
char temppath[MAXPATHLEN];
if(type == FILE_ROM)
{
// Check path length
if ((strlen(browser.dir)+1+strlen(browserList[browser.selIndex].filename)) >= MAXPATHLEN)
{
ErrorPrompt("Maximum filepath length reached!");
filepath[0] = 0;
return false;
}
else
{
sprintf(temppath, "%s/%s",browser.dir,browserList[browser.selIndex].filename);
}
}
else
{
switch(type)
{
case FILE_SRAM:
case FILE_SNAPSHOT:
sprintf(folder, GCSettings.SaveFolder);
if(type == FILE_SRAM) sprintf(ext, "sav");
else sprintf(ext, "sgm");
if(filenum >= -1)
{
if(method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB)
{
if(filenum > 9)
{
return false;
}
else if(filenum == -1)
{
filename[27] = 0; // truncate filename
sprintf(file, "%s.%s", filename, ext);
}
else
{
filename[26] = 0; // truncate filename
sprintf(file, "%s%i.%s", filename, filenum, ext);
}
}
else
{
if(filenum == -1)
sprintf(file, "%s.%s", filename, ext);
else if(filenum == 0)
sprintf(file, "%s Auto.%s", filename, ext);
else
sprintf(file, "%s %i.%s", filename, filenum, ext);
}
}
else
{
sprintf(file, "%s", filename);
}
break;
case FILE_CHEAT:
sprintf(folder, GCSettings.CheatFolder);
sprintf(file, "%s.cht", ROMFilename);
break;
case FILE_PREF:
sprintf(folder, appPath);
sprintf(file, "%s", PREF_FILE_NAME);
break;
}
switch(method)
{
case METHOD_MC_SLOTA:
case METHOD_MC_SLOTB:
sprintf (temppath, "%s", file);
temppath[31] = 0; // truncate filename
break;
default:
sprintf (temppath, "%s/%s", folder, file);
break;
}
}
strncpy(filepath, temppath, MAXPATHLEN);
return true;
}
/****************************************************************************
* FileSortCallback
*
* Quick sort callback to sort file entries with the following order:
* .
* ..
* <dirs>
* <files>
***************************************************************************/
int FileSortCallback(const void *f1, const void *f2)
{
/* Special case for implicit directories */
if(((BROWSERENTRY *)f1)->filename[0] == '.' || ((BROWSERENTRY *)f2)->filename[0] == '.')
{
if(strcmp(((BROWSERENTRY *)f1)->filename, ".") == 0) { return -1; }
if(strcmp(((BROWSERENTRY *)f2)->filename, ".") == 0) { return 1; }
if(strcmp(((BROWSERENTRY *)f1)->filename, "..") == 0) { return -1; }
if(strcmp(((BROWSERENTRY *)f2)->filename, "..") == 0) { return 1; }
}
/* If one is a file and one is a directory the directory is first. */
if(((BROWSERENTRY *)f1)->isdir && !(((BROWSERENTRY *)f2)->isdir)) return -1;
if(!(((BROWSERENTRY *)f1)->isdir) && ((BROWSERENTRY *)f2)->isdir) return 1;
return stricmp(((BROWSERENTRY *)f1)->filename, ((BROWSERENTRY *)f2)->filename);
}
/****************************************************************************
* IsSz
*
* Checks if the specified file is a 7z
***************************************************************************/
bool IsSz()
{
if (strlen(browserList[browser.selIndex].filename) > 4)
{
char * p = strrchr(browserList[browser.selIndex].filename, '.');
if (p != NULL)
if(stricmp(p, ".7z") == 0)
return true;
}
return false;
}
/****************************************************************************
* StripExt
*
* Strips an extension from a filename
***************************************************************************/
void StripExt(char* returnstring, char * inputstring)
{
char* loc_dot;
strncpy (returnstring, inputstring, 255);
if(inputstring == NULL || strlen(inputstring) < 4)
return;
loc_dot = strrchr(returnstring,'.');
if (loc_dot != NULL)
*loc_dot = 0; // strip file extension
}
// Shorten a ROM filename by removing the extension, URLs, id numbers and other rubbish
void ShortenFilename(char * returnstring, char * inputstring)
{
if (!inputstring) {
returnstring[0] = '\0';
return;
}
// skip URLs in brackets
char * dotcom = (char *) strstr(inputstring, ".com)");
char * url = NULL;
if (dotcom) {
url = (char *) strchr(inputstring, '(');
if (url >= dotcom) {
url = NULL;
dotcom = NULL;
} else dotcom+= 5; // point to after ')'
}
// skip URLs not in brackets
if (!dotcom) {
dotcom = (char *) strstr(inputstring, ".com");
url = NULL;
if (dotcom) {
url = (char *) strstr(inputstring, "www");
if (url >= dotcom) {
url = NULL;
dotcom = NULL;
} else dotcom+= 4; // point to after ')'
}
}
// skip file extension
char * loc_dot = (char *)strrchr(inputstring,'.');
char * s = (char *)inputstring;
char * r = (char *)returnstring;
// skip initial whitespace, numbers, - and _ ...
while ((*s!='\0' && *s<=' ') || *s=='-' || *s=='_' || *s=='+') s++;
// ... except those that SHOULD begin with numbers
if (strncmp(s,"3D",2)==0) for (int i=0; i<2; i++, r++, s++) *r=*s;
if (strncmp(s,"1st",3)==0 || strncmp(s,"2nd",3)==0 || strncmp(s,"3rd",3)==0 || strncmp(s,"4th",3)==0) for (int i=0; i<3; i++, r++, s++) *r=*s;
if (strncmp(s,"199",3)==0 || strncmp(s,"007",3)==0 || strncmp(s,"4x4",3)==0 || strncmp(s,"720",3)==0 || strncmp(s,"10 ",3)==0) for (int i=0; i<3; i++, r++, s++) *r=*s;
if (strncmp(s,"102 ",4)==0 || strncmp(s,"1942",4)==0 || strncmp(s,"3 Ch",4)==0) for (int i=0; i<4; i++, r++, s++) *r=*s;
if (strncmp(s,"2 in 1",6)==0 || strncmp(s,"3 in 1",6)==0 || strncmp(s,"4 in 1",6)==0) for (int i=0; i<6; i++, r++, s++) *r=*s;
if (strncmp(s,"2-in-1",6)==0 || strncmp(s,"3-in-1",6)==0 || strncmp(s,"4-in-1",6)==0) for (int i=0; i<6; i++, r++, s++) *r=*s;
while (*s>='0' && *s<='9') s++;
if (r==(char *)returnstring) while ((*s!='\0' && *s<=' ') || *s=='-' || *s=='_' || *s=='+') s++;
// now go through rest of string until we get to the end or the extension
while (*s!='\0' && (loc_dot==NULL || s<loc_dot)) {
// skip url
if (s==url) s=dotcom;
// skip whitespace, numbers, - and _ after url
if (s==dotcom) {
while ((*s>'\0' && *s<=' ') || *s=='-' || *s=='_') s++;
while (*s>='0' && *s<='9') s++;
while ((*s>'\0' && *s<=' ') || *s=='-' || *s=='_') s++;
}
// skip all but 1 '-', '_' or space in a row
char c = s[0];
if (c==s[1] && (c=='-' || c=='_' || c==' ')) s++;
// skip space before hyphen
if (*s==' ' && s[1]=='-') s++;
// copy character to result
if (*s=='_') *r=' ';
else *r = *s;
// skip spaces after hyphen
if (*s=='-') while (s[1]==' ') s++;
s++; r++;
}
*r = '\0';
// if the result is too short, abandon what we did and just strip the ext instead
if (strlen(returnstring) <= 4) StripExt(returnstring, inputstring);
}
/****************************************************************************
* BrowserLoadSz
*
* Opens the selected 7z file, and parses a listing of the files within
***************************************************************************/
int BrowserLoadSz(int method)
{
char filepath[MAXPATHLEN];
memset(filepath, 0, MAXPATHLEN);
// we'll store the 7z filepath for extraction later
if(!MakeFilePath(szpath, FILE_ROM, method))
return 0;
// add device to filepath
if(method != METHOD_DVD)
{
sprintf(filepath, "%s%s", rootdir, szpath);
memcpy(szpath, filepath, MAXPATHLEN);
}
int szfiles = SzParse(szpath, method);
if(szfiles)
{
browser.numEntries = szfiles;
inSz = true;
}
else
ErrorPrompt("Error opening archive!");
return szfiles;
}
/****************************************************************************
* BrowserLoadFile
*
* Loads the selected ROM
***************************************************************************/
int BrowserLoadFile(int method)
{
// store the filename (w/o ext) - used for sram/freeze naming
StripExt(ROMFilename, browserList[browser.selIndex].filename);
ROMLoaded = LoadVBAROM(method);
inSz = false;
if (!ROMLoaded)
{
ErrorPrompt("Error loading ROM!");
}
else
{
if (GCSettings.AutoLoad == 1)
LoadBatteryOrStateAuto(GCSettings.SaveMethod, FILE_SRAM, SILENT);
else if (GCSettings.AutoLoad == 2)
LoadBatteryOrStateAuto(GCSettings.SaveMethod, FILE_SNAPSHOT, SILENT);
ResetBrowser();
}
CancelAction();
return ROMLoaded;
}
/****************************************************************************
* BrowserChangeFolder
*
* Update current directory and set new entry list if directory has changed
***************************************************************************/
int BrowserChangeFolder(int method)
{
if(inSz && browser.selIndex == 0) // inside a 7z, requesting to leave
{
if(method == METHOD_DVD)
SetDVDdirectory(browserList[0].offset, browserList[0].length);
inSz = false;
SzClose();
}
if(!UpdateDirName(method))
return -1;
switch (method)
{
case METHOD_DVD:
ParseDVDdirectory();
break;
default:
ParseDirectory(method);
break;
}
if (!browser.numEntries)
{
ErrorPrompt("Error reading directory!");
}
return browser.numEntries;
}
/****************************************************************************
* OpenROM
* Displays a list of ROMS on load device
***************************************************************************/
int
OpenGameList ()
{
int method = GCSettings.LoadMethod;
if(method == METHOD_AUTO)
method = autoLoadMethod();
// change current dir to roms directory
switch(method)
{
case METHOD_DVD:
browser.dir[0] = 0;
if(MountDVD(NOTSILENT))
if(ParseDVDdirectory()) // Parse root directory
SwitchDVDFolder(GCSettings.LoadFolder); // switch to ROM folder
break;
default:
sprintf(browser.dir, "/%s", GCSettings.LoadFolder);
ParseDirectory(method); // Parse root directory
break;
}
return browser.numEntries;
}

View File

@ -5,8 +5,7 @@
* *
* filelist.h * filelist.h
* *
* Contains a list of all of the files stored in the images/, fonts/, and * Contains a list of all of the files in the images/ folder
* sounds/ folders
***************************************************************************/ ***************************************************************************/
#ifndef _FILELIST_H_ #ifndef _FILELIST_H_
@ -17,208 +16,6 @@
extern const u8 font_ttf[]; extern const u8 font_ttf[];
extern const u32 font_ttf_size; extern const u32 font_ttf_size;
extern const u8 bg_music_ogg[];
extern const u32 bg_music_ogg_size;
extern const u8 enter_ogg[];
extern const u32 enter_ogg_size;
extern const u8 exit_ogg[];
extern const u32 exit_ogg_size;
extern const u8 button_over_pcm[];
extern const u32 button_over_pcm_size;
extern const u8 button_click_pcm[];
extern const u32 button_click_pcm_size;
extern const u8 logo_png[];
extern const u32 logo_png_size;
extern const u8 logo_over_png[];
extern const u32 logo_over_png_size;
extern const u8 bg_top_png[];
extern const u32 bg_top_png_size;
extern const u8 bg_bottom_png[];
extern const u32 bg_bottom_png_size;
extern const u8 icon_settings_png[];
extern const u32 icon_settings_png_size;
extern const u8 icon_home_png[];
extern const u32 icon_home_png_size;
extern const u8 icon_game_cheats_png[];
extern const u32 icon_game_cheats_png_size;
extern const u8 icon_game_controllers_png[];
extern const u32 icon_game_controllers_png_size;
extern const u8 icon_game_load_png[];
extern const u32 icon_game_load_png_size;
extern const u8 icon_game_save_png[];
extern const u32 icon_game_save_png_size;
extern const u8 icon_game_reset_png[];
extern const u32 icon_game_reset_png_size;
extern const u8 icon_settings_wiimote_png[];
extern const u32 icon_settings_wiimote_png_size;
extern const u8 icon_settings_classic_png[];
extern const u32 icon_settings_classic_png_size;
extern const u8 icon_settings_gamecube_png[];
extern const u32 icon_settings_gamecube_png_size;
extern const u8 icon_settings_nunchuk_png[];
extern const u32 icon_settings_nunchuk_png_size;
extern const u8 icon_settings_file_png[];
extern const u32 icon_settings_file_png_size;
extern const u8 icon_settings_mappings_png[];
extern const u32 icon_settings_mappings_png_size;
extern const u8 icon_settings_menu_png[];
extern const u32 icon_settings_menu_png_size;
extern const u8 icon_settings_network_png[];
extern const u32 icon_settings_network_png_size;
extern const u8 icon_settings_video_png[];
extern const u32 icon_settings_video_png_size;
extern const u8 button_png[];
extern const u32 button_png_size;
extern const u8 button_over_png[];
extern const u32 button_over_png_size;
extern const u8 button_small_png[];
extern const u32 button_small_png_size;
extern const u8 button_small_over_png[];
extern const u32 button_small_over_png_size;
extern const u8 button_large_png[];
extern const u32 button_large_png_size;
extern const u8 button_large_over_png[];
extern const u32 button_large_over_png_size;
extern const u8 button_arrow_left_png[];
extern const u32 button_arrow_left_png_size;
extern const u8 button_arrow_right_png[];
extern const u32 button_arrow_right_png_size;
extern const u8 button_arrow_up_png[];
extern const u32 button_arrow_up_png_size;
extern const u8 button_arrow_down_png[];
extern const u32 button_arrow_down_png_size;
extern const u8 button_arrow_left_over_png[];
extern const u32 button_arrow_left_over_png_size;
extern const u8 button_arrow_right_over_png[];
extern const u32 button_arrow_right_over_png_size;
extern const u8 button_arrow_up_over_png[];
extern const u32 button_arrow_up_over_png_size;
extern const u8 button_arrow_down_over_png[];
extern const u32 button_arrow_down_over_png_size;
extern const u8 button_gamesave_png[];
extern const u32 button_gamesave_png_size;
extern const u8 button_gamesave_over_png[];
extern const u32 button_gamesave_over_png_size;
extern const u8 button_gamesave_blank_png[];
extern const u32 button_gamesave_blank_png_size;
extern const u8 screen_position_png[];
extern const u32 screen_position_png_size;
extern const u8 dialogue_box_png[];
extern const u32 dialogue_box_png_size;
extern const u8 credits_box_png[];
extern const u32 credits_box_png_size;
extern const u8 progressbar_png[];
extern const u32 progressbar_png_size;
extern const u8 progressbar_empty_png[];
extern const u32 progressbar_empty_png_size;
extern const u8 progressbar_outline_png[];
extern const u32 progressbar_outline_png_size;
extern const u8 throbber_png[];
extern const u32 throbber_png_size;
extern const u8 folder_png[];
extern const u32 folder_png_size;
extern const u8 battery_png[];
extern const u32 battery_png_size;
extern const u8 battery_red_png[];
extern const u32 battery_red_png_size;
extern const u8 battery_bar_png[];
extern const u32 battery_bar_png_size;
extern const u8 bg_options_png[];
extern const u32 bg_options_png_size;
extern const u8 bg_options_entry_png[];
extern const u32 bg_options_entry_png_size;
extern const u8 bg_game_selection_png[];
extern const u32 bg_game_selection_png_size;
extern const u8 bg_game_selection_entry_png[];
extern const u32 bg_game_selection_entry_png_size;
extern const u8 scrollbar_png[];
extern const u32 scrollbar_png_size;
extern const u8 scrollbar_arrowup_png[];
extern const u32 scrollbar_arrowup_png_size;
extern const u8 scrollbar_arrowup_over_png[];
extern const u32 scrollbar_arrowup_over_png_size;
extern const u8 scrollbar_arrowdown_png[];
extern const u32 scrollbar_arrowdown_png_size;
extern const u8 scrollbar_arrowdown_over_png[];
extern const u32 scrollbar_arrowdown_over_png_size;
extern const u8 scrollbar_box_png[];
extern const u32 scrollbar_box_png_size;
extern const u8 scrollbar_box_over_png[];
extern const u32 scrollbar_box_over_png_size;
extern const u8 keyboard_textbox_png[];
extern const u32 keyboard_textbox_png_size;
extern const u8 keyboard_key_png[];
extern const u32 keyboard_key_png_size;
extern const u8 keyboard_key_over_png[];
extern const u32 keyboard_key_over_png_size;
extern const u8 keyboard_mediumkey_png[];
extern const u32 keyboard_mediumkey_png_size;
extern const u8 keyboard_mediumkey_over_png[];
extern const u32 keyboard_mediumkey_over_png_size;
extern const u8 keyboard_largekey_png[];
extern const u32 keyboard_largekey_png_size;
extern const u8 keyboard_largekey_over_png[];
extern const u32 keyboard_largekey_over_png_size;
extern const u8 player1_point_png[]; extern const u8 player1_point_png[];
extern const u32 player1_point_png_size; extern const u32 player1_point_png_size;

View File

@ -29,8 +29,8 @@
#include "memcardop.h" #include "memcardop.h"
#include "gcunzip.h" #include "gcunzip.h"
#include "video.h" #include "video.h"
#include "menu.h" #include "menudraw.h"
#include "filebrowser.h" #include "filesel.h"
#include "preferences.h" #include "preferences.h"
unsigned char * savebuffer = NULL; unsigned char * savebuffer = NULL;
@ -49,7 +49,7 @@ bool isMounted[9] = { false, false, false, false, false, false, false, false, fa
/**************************************************************************** /****************************************************************************
* deviceThreading * deviceThreading
***************************************************************************/ ***************************************************************************/
lwp_t devicethread = LWP_THREAD_NULL; lwp_t devicethread;
/**************************************************************************** /****************************************************************************
* devicecallback * devicecallback
@ -103,6 +103,7 @@ devicecallback (void *arg)
#endif #endif
usleep(500000); // suspend thread for 1/2 sec usleep(500000); // suspend thread for 1/2 sec
} }
return NULL; return NULL;
} }
@ -115,7 +116,7 @@ devicecallback (void *arg)
void void
InitDeviceThread() InitDeviceThread()
{ {
LWP_CreateThread (&devicethread, devicecallback, NULL, NULL, 0, 40); LWP_CreateThread (&devicethread, devicecallback, NULL, NULL, 0, 80);
} }
/**************************************************************************** /****************************************************************************
@ -180,7 +181,6 @@ bool MountFAT(int method)
unmountRequired[method] = false; unmountRequired[method] = false;
fatUnmount(rootdir); fatUnmount(rootdir);
disc->shutdown(); disc->shutdown();
isMounted[method] = false;
} }
if(!isMounted[method]) if(!isMounted[method])
{ {
@ -227,7 +227,7 @@ bool ChangeInterface(int method, bool silent)
mounted = MountFAT(METHOD_SD_SLOTB); // try SD Gecko on slot B mounted = MountFAT(METHOD_SD_SLOTB); // try SD Gecko on slot B
#endif #endif
if(!mounted && !silent) // no SD device found if(!mounted && !silent) // no SD device found
ErrorPrompt("SD card not found!"); WaitPrompt ("SD card not found!");
} }
else if(method == METHOD_USB) else if(method == METHOD_USB)
{ {
@ -235,31 +235,19 @@ bool ChangeInterface(int method, bool silent)
mounted = MountFAT(method); mounted = MountFAT(method);
if(!mounted && !silent) if(!mounted && !silent)
ErrorPrompt("USB drive not found!"); WaitPrompt ("USB drive not found!");
#endif #endif
} }
else if(method == METHOD_DVD) else if(method == METHOD_DVD)
{ {
rootdir[0] = 0; sprintf(rootdir, "/");
mounted = MountDVD(silent); mounted = MountDVD(silent);
} }
#ifdef HW_RVL
else if(method == METHOD_SMB) else if(method == METHOD_SMB)
{ {
sprintf(rootdir, "smb:/"); sprintf(rootdir, "smb:/");
mounted = ConnectShare(silent); mounted = ConnectShare(silent);
} }
#endif
else if(method == METHOD_MC_SLOTA)
{
rootdir[0] = 0;
mounted = TestMC(CARD_SLOTA, silent);
}
else if(method == METHOD_MC_SLOTB)
{
rootdir[0] = 0;
mounted = TestMC(CARD_SLOTB, silent);
}
return mounted; return mounted;
} }
@ -268,49 +256,39 @@ bool ChangeInterface(int method, bool silent)
* Browse subdirectories * Browse subdirectories
**************************************************************************/ **************************************************************************/
int int
ParseDirectory(int method) ParseDirectory()
{ {
DIR_ITER *dir = NULL; DIR_ITER *dir;
char fulldir[MAXPATHLEN]; char fulldir[MAXPATHLEN];
char filename[MAXPATHLEN]; char filename[MAXPATHLEN];
char tmpname[MAXPATHLEN]; char tmpname[MAXPATHLEN];
struct stat filestat; struct stat filestat;
char msg[128]; char msg[128];
int retry = 1;
bool mounted = false;
// reset browser // reset browser
ResetBrowser(); ResetBrowser();
ShowAction("Loading..."); // add device to path
sprintf(fulldir, "%s%s", rootdir, browser.dir);
// open the directory // open the directory
while(dir == NULL && retry == 1) dir = diropen(fulldir);
{
mounted = ChangeInterface(method, NOTSILENT);
sprintf(fulldir, "%s%s", rootdir, browser.dir); // add device to path
if(mounted) dir = diropen(fulldir);
if(dir == NULL)
{
unmountRequired[method] = true;
sprintf(msg, "Error opening %s", fulldir);
retry = ErrorPromptRetry(msg);
}
}
// if we can't open the dir, try opening the root dir
if (dir == NULL) if (dir == NULL)
{ {
if(ChangeInterface(method, SILENT)) sprintf(msg, "Error opening %s", fulldir);
WaitPrompt(msg);
// if we can't open the dir, open root dir
sprintf(browser.dir,"/");
dir = diropen(rootdir);
if (dir == NULL)
{ {
sprintf(browser.dir,"/"); sprintf(msg, "Error opening %s", rootdir);
dir = diropen(rootdir); WaitPrompt(msg);
if (dir == NULL) return 0;
{
sprintf(msg, "Error opening %s", rootdir);
ErrorPrompt(msg);
return -1;
}
} }
} }
@ -326,8 +304,8 @@ ParseDirectory(int method)
if(!newBrowserList) // failed to allocate required memory if(!newBrowserList) // failed to allocate required memory
{ {
ResetBrowser(); ResetBrowser();
ErrorPrompt("Out of memory: too many files!"); WaitPrompt("Out of memory: too many files!");
entryNum = -1; entryNum = 0;
break; break;
} }
else else
@ -337,19 +315,9 @@ ParseDirectory(int method)
memset(&(browserList[entryNum]), 0, sizeof(BROWSERENTRY)); // clear the new entry memset(&(browserList[entryNum]), 0, sizeof(BROWSERENTRY)); // clear the new entry
strncpy(browserList[entryNum].filename, filename, MAXJOLIET); strncpy(browserList[entryNum].filename, filename, MAXJOLIET);
StripExt(tmpname, filename); // hide file extension
if(strcmp(filename,"..") == 0) strncpy(browserList[entryNum].displayname, tmpname, MAXDISPLAY); // crop name for display
{
sprintf(browserList[entryNum].displayname, "Up One Level");
}
else
{
ShortenFilename(tmpname, filename); // hide file extension
strncpy(browserList[entryNum].displayname, tmpname, MAXDISPLAY); // crop name for display
}
browserList[entryNum].length = filestat.st_size; browserList[entryNum].length = filestat.st_size;
browserList[entryNum].mtime = filestat.st_mtime;
browserList[entryNum].isdir = (filestat.st_mode & _IFDIR) == 0 ? 0 : 1; // flag this as a dir browserList[entryNum].isdir = (filestat.st_mode & _IFDIR) == 0 ? 0 : 1; // flag this as a dir
entryNum++; entryNum++;
@ -362,9 +330,6 @@ ParseDirectory(int method)
// Sort the file list // Sort the file list
qsort(browserList, entryNum, sizeof(BROWSERENTRY), FileSortCallback); qsort(browserList, entryNum, sizeof(BROWSERENTRY), FileSortCallback);
CancelAction();
browser.numEntries = entryNum;
return entryNum; return entryNum;
} }
@ -375,8 +340,8 @@ ParseDirectory(int method)
void void
AllocSaveBuffer () AllocSaveBuffer ()
{ {
while(savebuffer != NULL) // save buffer is in use if (savebuffer != NULL)
usleep(50); // wait for it to be free free(savebuffer);
savebuffer = (unsigned char *) memalign(32, SAVEBUFFERSIZE); savebuffer = (unsigned char *) memalign(32, SAVEBUFFERSIZE);
memset (savebuffer, 0, SAVEBUFFERSIZE); memset (savebuffer, 0, SAVEBUFFERSIZE);
@ -417,7 +382,7 @@ LoadSzFile(char * filepath, unsigned char * rbuffer)
} }
else else
{ {
ErrorPrompt("Error opening file"); WaitPrompt("Error opening file");
} }
// go back to checking if devices were inserted/removed // go back to checking if devices were inserted/removed
@ -435,8 +400,9 @@ LoadFile (char * rbuffer, char *filepath, u32 length, int method, bool silent)
char zipbuffer[2048]; char zipbuffer[2048];
u32 size = 0; u32 size = 0;
u32 readsize = 0; u32 readsize = 0;
char fullpath[MAXPATHLEN];
int retry = 1; if(!ChangeInterface(method, NOTSILENT))
return 0;
switch(method) switch(method)
{ {
@ -455,84 +421,69 @@ LoadFile (char * rbuffer, char *filepath, u32 length, int method, bool silent)
// since we're loading a file // since we're loading a file
LWP_SuspendThread (devicethread); LWP_SuspendThread (devicethread);
// open the file // add device to filepath
while(!size && retry == 1) char fullpath[1024];
sprintf(fullpath, "%s%s", rootdir, filepath);
file = fopen (fullpath, "rb");
if (file > 0)
{ {
if(ChangeInterface(method, silent)) if(length > 0 && length <= 2048) // do a partial read (eg: to check file header)
{ {
sprintf(fullpath, "%s%s", rootdir, filepath); // add device to filepath size = fread (rbuffer, 1, length, file);
file = fopen (fullpath, "rb"); }
else // load whole file
{
readsize = fread (zipbuffer, 1, 2048, file);
if(file > 0) if(readsize > 0)
{ {
if(length > 0 && length <= 2048) // do a partial read (eg: to check file header) if (IsZipFile (zipbuffer))
{ {
size = fread (rbuffer, 1, length, file); size = UnZipBuffer ((unsigned char *)rbuffer, method); // unzip
} }
else // load whole file else
{ {
readsize = fread (zipbuffer, 1, 2048, file); struct stat fileinfo;
fstat(file->_file, &fileinfo);
size = fileinfo.st_size;
if(readsize > 0) memcpy (rbuffer, zipbuffer, readsize); // copy what we already read
u32 offset = readsize;
while(offset < size)
{ {
if (IsZipFile (zipbuffer)) ShowProgress ("Loading...", offset, size);
{ readsize = fread (rbuffer + offset, 1, (1024*512), file); // read in 512K chunks
size = UnZipBuffer ((unsigned char *)rbuffer, method); // unzip
}
else
{
struct stat fileinfo;
fstat(file->_file, &fileinfo);
size = fileinfo.st_size;
memcpy (rbuffer, zipbuffer, readsize); // copy what we already read if(readsize <= 0 || readsize > (1024*512))
break; // read failure
u32 offset = readsize; if(readsize > 0)
u32 nextread = 0; offset += readsize;
while(offset < size)
{
if(size - offset > 1024*512) nextread = 1024*512;
else nextread = size-offset;
ShowProgress ("Loading...", offset, size);
readsize = fread (rbuffer + offset, 1, nextread, file); // read in next chunk
if(readsize <= 0 || readsize > nextread)
break; // read failure
if(readsize > 0)
offset += readsize;
}
CancelAction();
if(offset != size) // # bytes read doesn't match # expected
size = 0;
}
} }
if(offset != size) // # bytes read doesn't match # expected
size = 0;
} }
fclose (file);
}
}
if(!size)
{
if(!silent)
{
unmountRequired[method] = true;
retry = ErrorPromptRetry("Error loading file!");
}
else
{
retry = 0;
} }
} }
fclose (file);
}
if(!size && !silent)
{
unmountRequired[method] = true;
WaitPrompt("Error loading file!");
} }
// go back to checking if devices were inserted/removed // go back to checking if devices were inserted/removed
LWP_ResumeThread (devicethread); LWP_ResumeThread (devicethread);
CancelAction();
return size; return size;
} }
u32 LoadFile(char * filepath, int method, bool silent) u32 LoadFile(char filepath[], int method, bool silent)
{ {
return LoadFile((char *)savebuffer, filepath, 0, method, silent); return LoadFile((char *)savebuffer, filepath, 0, method, silent);
} }
@ -544,59 +495,53 @@ u32 LoadFile(char * filepath, int method, bool silent)
u32 u32
SaveFile (char * buffer, char *filepath, u32 datasize, int method, bool silent) SaveFile (char * buffer, char *filepath, u32 datasize, int method, bool silent)
{ {
char fullpath[MAXPATHLEN];
u32 written = 0; u32 written = 0;
int retry = 1;
if(datasize == 0) if(!ChangeInterface(method, NOTSILENT))
return 0; return 0;
ShowAction("Saving..."); switch(method)
if(method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB)
{ {
if(method == METHOD_MC_SLOTA) case METHOD_MC_SLOTA:
return SaveMCFile (buffer, CARD_SLOTA, filepath, datasize, silent); return SaveMCFile (buffer, CARD_SLOTA, filepath, datasize, silent);
else break;
case METHOD_MC_SLOTB:
return SaveMCFile (buffer, CARD_SLOTB, filepath, datasize, silent); return SaveMCFile (buffer, CARD_SLOTB, filepath, datasize, silent);
break;
} }
// stop checking if devices were removed/inserted if (datasize)
// since we're saving a file {
LWP_SuspendThread (devicethread); // stop checking if devices were removed/inserted
// since we're saving a file
LWP_SuspendThread (devicethread);
while(!written && retry == 1) // add device to filepath
{ char fullpath[1024];
if(ChangeInterface(method, silent)) sprintf(fullpath, "%s%s", rootdir, filepath);
// open file for writing
file = fopen (fullpath, "wb");
if (file > 0)
{ {
sprintf(fullpath, "%s%s", rootdir, filepath); // add device to filepath written = fwrite (savebuffer, 1, datasize, file);
file = fopen (fullpath, "wb"); fclose (file);
if (file > 0)
{
written = fwrite (savebuffer, 1, datasize, file);
if(written < datasize) written = 0;
fclose (file);
}
} }
if(!written)
if(!written && !silent)
{ {
unmountRequired[method] = true; unmountRequired[method] = true;
if(!silent) WaitPrompt ("Error saving file!");
retry = ErrorPromptRetry("Error saving file!");
else
retry = 0;
} }
}
// go back to checking if devices were inserted/removed // go back to checking if devices were inserted/removed
LWP_ResumeThread (devicethread); LWP_ResumeThread (devicethread);
}
CancelAction();
return written; return written;
} }
u32 SaveFile(char * filepath, u32 datasize, int method, bool silent) u32 SaveFile(char filepath[], u32 datasize, int method, bool silent)
{ {
return SaveFile((char *)savebuffer, filepath, datasize, method, silent); return SaveFile((char *)savebuffer, filepath, datasize, method, silent);
} }

View File

@ -24,14 +24,14 @@ void InitDeviceThread();
void MountAllFAT(); void MountAllFAT();
void UnmountAllFAT(); void UnmountAllFAT();
bool ChangeInterface(int method, bool silent); bool ChangeInterface(int method, bool silent);
int ParseDirectory(int method); int ParseDirectory();
void AllocSaveBuffer(); void AllocSaveBuffer();
void FreeSaveBuffer(); void FreeSaveBuffer();
u32 LoadFile(char * rbuffer, char *filepath, u32 length, int method, bool silent); u32 LoadFile(char * rbuffer, char *filepath, u32 length, int method, bool silent);
u32 LoadFile(char * filepath, int method, bool silent); u32 LoadFile(char filepath[], int method, bool silent);
u32 LoadSzFile(char * filepath, unsigned char * rbuffer); u32 LoadSzFile(char * filepath, unsigned char * rbuffer);
u32 SaveFile(char * buffer, char *filepath, u32 datasize, int method, bool silent); u32 SaveFile(char * buffer, char *filepath, u32 datasize, int method, bool silent);
u32 SaveFile(char * filepath, u32 datasize, int method, bool silent); u32 SaveFile(char filepath[], u32 datasize, int method, bool silent);
extern unsigned char * savebuffer; extern unsigned char * savebuffer;
extern FILE * file; extern FILE * file;

582
source/ngc/filesel.cpp Normal file
View File

@ -0,0 +1,582 @@
/****************************************************************************
* Visual Boy Advance GX
*
* Tantric September 2008
*
* filesel.cpp
*
* Generic file routines - reading, writing, browsing
***************************************************************************/
#include <gccore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wiiuse/wpad.h>
#include <sys/dir.h>
#include <malloc.h>
#ifdef HW_RVL
extern "C" {
#include <di/di.h>
}
#endif
#include "vba.h"
#include "vbasupport.h"
#include "vmmem.h"
#include "menudraw.h"
#include "video.h"
#include "fileop.h"
#include "filesel.h"
#include "memcardop.h"
#include "input.h"
#include "dvd.h"
#include "networkop.h"
#include "gcunzip.h"
#include "wiiusbsupport.h"
BROWSERINFO browser;
BROWSERENTRY * browserList = NULL; // list of files/folders in browser
char rootdir[10];
char szpath[MAXPATHLEN];
bool inSz = false;
char ROMFilename[512];
bool ROMLoaded = false;
/****************************************************************************
* autoLoadMethod()
* Auto-determines and sets the load method
* Returns method set
****************************************************************************/
int autoLoadMethod()
{
ShowAction ("Attempting to determine load method...");
int method = 0;
if(ChangeInterface(METHOD_SD, SILENT))
method = METHOD_SD;
else if(ChangeInterface(METHOD_USB, SILENT))
method = METHOD_USB;
else if(ChangeInterface(METHOD_DVD, SILENT))
method = METHOD_DVD;
else if(ChangeInterface(METHOD_SMB, SILENT))
method = METHOD_SMB;
else
WaitPrompt("Unable to auto-determine load method!");
if(GCSettings.LoadMethod == METHOD_AUTO)
GCSettings.LoadMethod = method; // save method found for later use
return method;
}
/****************************************************************************
* autoSaveMethod()
* Auto-determines and sets the save method
* Returns method set
****************************************************************************/
int autoSaveMethod(bool silent)
{
if(!silent)
ShowAction ("Attempting to determine save method...");
int method = 0;
if(ChangeInterface(METHOD_SD, SILENT))
method = METHOD_SD;
else if(ChangeInterface(METHOD_USB, SILENT))
method = METHOD_USB;
else if(TestCard(CARD_SLOTA, SILENT))
method = METHOD_MC_SLOTA;
else if(TestCard(CARD_SLOTB, SILENT))
method = METHOD_MC_SLOTB;
else if(ChangeInterface(METHOD_SMB, SILENT))
method = METHOD_SMB;
else if(!silent)
WaitPrompt("Unable to auto-determine save method!");
if(GCSettings.SaveMethod == METHOD_AUTO)
GCSettings.SaveMethod = method; // save method found for later use
return method;
}
/****************************************************************************
* ResetBrowser()
* Clears the file browser memory, and allocates one initial entry
***************************************************************************/
void ResetBrowser()
{
browser.selIndex = browser.pageIndex = 0;
// Clear any existing values
if(browserList != NULL)
{
free(browserList);
browserList = NULL;
}
// set aside space for 1 entry
browserList = (BROWSERENTRY *)memalign(32, sizeof(BROWSERENTRY));
memset(browserList, 0, sizeof(BROWSERENTRY));
}
/****************************************************************************
* UpdateDirName()
* Update curent directory name for file browser
***************************************************************************/
int UpdateDirName(int method)
{
int size=0;
char * test;
char temp[1024];
// update DVD directory
if(method == METHOD_DVD)
SetDVDdirectory(browserList[browser.selIndex].offset, browserList[browser.selIndex].length);
/* current directory doesn't change */
if (strcmp(browserList[browser.selIndex].filename,".") == 0)
{
return 0;
}
/* go up to parent directory */
else if (strcmp(browserList[browser.selIndex].filename,"..") == 0)
{
/* determine last subdirectory namelength */
sprintf(temp,"%s",browser.dir);
test = strtok(temp,"/");
while (test != NULL)
{
size = strlen(test);
test = strtok(NULL,"/");
}
/* remove last subdirectory name */
size = strlen(browser.dir) - size - 1;
browser.dir[size] = 0;
return 1;
}
/* Open a directory */
else
{
/* test new directory namelength */
if ((strlen(browser.dir)+1+strlen(browserList[browser.selIndex].filename)) < MAXPATHLEN)
{
/* update current directory name */
sprintf(browser.dir, "%s/%s",browser.dir, browserList[browser.selIndex].filename);
return 1;
}
else
{
WaitPrompt("Directory name is too long!");
return -1;
}
}
}
bool MakeFilePath(char filepath[], int type, int method)
{
char file[512];
char folder[1024];
char temppath[MAXPATHLEN];
if(type == FILE_ROM)
{
// Check path length
if ((strlen(browser.dir)+1+strlen(browserList[browser.selIndex].filename)) >= MAXPATHLEN)
{
WaitPrompt("Maximum filepath length reached!");
filepath[0] = 0;
return false;
}
else
{
sprintf(temppath, "%s/%s",browser.dir,browserList[browser.selIndex].filename);
}
}
else
{
switch(type)
{
case FILE_SRAM:
sprintf(folder, GCSettings.SaveFolder);
sprintf(file, "%s.sav", ROMFilename);
break;
case FILE_SNAPSHOT:
sprintf(folder, GCSettings.SaveFolder);
sprintf(file, "%s.sgm", ROMFilename);
break;
case FILE_CHEAT:
sprintf(folder, GCSettings.CheatFolder);
sprintf(file, "%s.cht", ROMFilename);
break;
case FILE_PREF:
sprintf(folder, appPath);
sprintf(file, "%s", PREF_FILE_NAME);
break;
}
switch(method)
{
case METHOD_MC_SLOTA:
case METHOD_MC_SLOTB:
sprintf (temppath, "%s", file);
temppath[31] = 0; // truncate filename
break;
default:
sprintf (temppath, "%s/%s", folder, file);
break;
}
}
strcpy(filepath, temppath);
return true;
}
/****************************************************************************
* FileSortCallback
*
* Quick sort callback to sort file entries with the following order:
* .
* ..
* <dirs>
* <files>
***************************************************************************/
int FileSortCallback(const void *f1, const void *f2)
{
/* Special case for implicit directories */
if(((BROWSERENTRY *)f1)->filename[0] == '.' || ((BROWSERENTRY *)f2)->filename[0] == '.')
{
if(strcmp(((BROWSERENTRY *)f1)->filename, ".") == 0) { return -1; }
if(strcmp(((BROWSERENTRY *)f2)->filename, ".") == 0) { return 1; }
if(strcmp(((BROWSERENTRY *)f1)->filename, "..") == 0) { return -1; }
if(strcmp(((BROWSERENTRY *)f2)->filename, "..") == 0) { return 1; }
}
/* If one is a file and one is a directory the directory is first. */
if(((BROWSERENTRY *)f1)->isdir && !(((BROWSERENTRY *)f2)->isdir)) return -1;
if(!(((BROWSERENTRY *)f1)->isdir) && ((BROWSERENTRY *)f2)->isdir) return 1;
return stricmp(((BROWSERENTRY *)f1)->filename, ((BROWSERENTRY *)f2)->filename);
}
/****************************************************************************
* IsSz
*
* Checks if the specified file is a 7z
***************************************************************************/
bool IsSz()
{
if (strlen(browserList[browser.selIndex].filename) > 4)
{
char * p = strrchr(browserList[browser.selIndex].filename, '.');
if (p != NULL)
if(stricmp(p, ".7z") == 0)
return true;
}
return false;
}
/****************************************************************************
* StripExt
*
* Strips an extension from a filename
***************************************************************************/
void StripExt(char* returnstring, char * inputstring)
{
char* loc_dot;
strcpy (returnstring, inputstring);
loc_dot = strrchr(returnstring,'.');
if (loc_dot != NULL)
*loc_dot = 0; // strip file extension
}
/****************************************************************************
* FileSelector
*
* Let user select a file from the listing
***************************************************************************/
int FileSelector (int method)
{
u32 p = 0;
u32 wp = 0;
u32 ph = 0;
u32 wh = 0;
signed char gc_ay = 0;
signed char gc_sx = 0;
signed char wm_ay = 0;
signed char wm_sx = 0;
int haverom = 0;
int redraw = 1;
int selectit = 0;
int scroll_delay = 0;
bool move_selection = 0;
#define SCROLL_INITIAL_DELAY 15
#define SCROLL_LOOP_DELAY 2
while (haverom == 0)
{
if (redraw)
ShowFiles (browserList, browser.numEntries, browser.pageIndex, browser.selIndex);
redraw = 0;
updateRumbleFrame();
VIDEO_WaitVSync(); // slow things down a bit so we don't overread the pads
gc_ay = PAD_StickY (0);
gc_sx = PAD_SubStickX (0);
p = PAD_ButtonsDown (0);
ph = PAD_ButtonsHeld (0);
#ifdef HW_RVL
wm_ay = WPAD_Stick (0, 0, 0);
wm_sx = WPAD_Stick (0, 1, 1);
wp = WPAD_ButtonsDown (0);
wh = WPAD_ButtonsHeld (0);
#endif
/*** Check for exit combo ***/
if ( (gc_sx < -70) || (wm_sx < -70) || (wp & WPAD_BUTTON_HOME) || (wp & WPAD_CLASSIC_BUTTON_HOME) || DownUsbKeys[KB_ESC])
return 0;
/*** Check buttons, perform actions ***/
if ( (p & PAD_BUTTON_A) || selectit || (wp & (WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A)) || DownUsbKeys[KB_ENTER] )
{
if ( selectit )
selectit = 0;
if (browserList[browser.selIndex].isdir) // This is directory
{
/* update current directory and set new entry list if directory has changed */
int status;
if(inSz && browser.selIndex == 0) // inside a 7z, requesting to leave
{
if(method == METHOD_DVD)
SetDVDdirectory(browserList[0].offset, browserList[0].length);
inSz = false;
status = 1;
SzClose();
}
else
{
status = UpdateDirName(method);
}
if (status == 1) // ok, open directory
{
switch (method)
{
case METHOD_DVD:
browser.numEntries = ParseDVDdirectory();
break;
default:
browser.numEntries = ParseDirectory();
break;
}
if (!browser.numEntries)
{
WaitPrompt ("Error reading directory!");
haverom = 1; // quit menu
}
}
else if (status == -1) // directory name too long
{
haverom = 1; // quit menu
}
}
else // this is a file
{
// 7z file - let's open it up to select a file inside
if(IsSz())
{
// we'll store the 7z filepath for extraction later
if(!MakeFilePath(szpath, FILE_ROM, method))
return 0;
// add device to filepath
char fullpath[1024];
sprintf(fullpath, "%s%s", rootdir, szpath);
strcpy(szpath, fullpath);
int szfiles = SzParse(szpath, method);
if(szfiles)
{
browser.numEntries = szfiles;
inSz = true;
}
else
WaitPrompt("Error opening archive!");
}
else
{
// store the filename (w/o ext) - used for sram/freeze naming
StripExt(ROMFilename, browserList[browser.selIndex].filename);
ShowAction ("Loading...");
ROMLoaded = LoadVBAROM(method);
inSz = false;
if (ROMLoaded)
{
return 1;
}
}
}
redraw = 1;
} // End of A
if ( (p & PAD_BUTTON_B) || (wp & (WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B) || DownUsbKeys[KB_BKSP]))
{
while ( (PAD_ButtonsDown(0) & PAD_BUTTON_B)
#ifdef HW_RVL
|| (WPAD_ButtonsDown(0) & (WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B))
#endif
) {
updateRumbleFrame();
VIDEO_WaitVSync();
}
if ( strcmp(browserList[0].filename,"..") == 0 )
{
browser.selIndex = 0;
selectit = 1;
}
else if ( strcmp(browserList[1].filename,"..") == 0 )
{
browser.selIndex = selectit = 1;
} else {
return 0;
}
} // End of B
if ( ((p | ph) & PAD_BUTTON_DOWN) || ((wp | wh) & (WPAD_BUTTON_DOWN | WPAD_CLASSIC_BUTTON_DOWN)) || (gc_ay < -PADCAL) || (wm_ay < -PADCAL) )
{
if ( (p & PAD_BUTTON_DOWN) || (wp & (WPAD_BUTTON_DOWN | WPAD_CLASSIC_BUTTON_DOWN)) ) { /*** Button just pressed ***/
scroll_delay = SCROLL_INITIAL_DELAY; // reset scroll delay.
move_selection = 1; //continue (move selection)
}
else if (scroll_delay == 0) { /*** Button is held ***/
scroll_delay = SCROLL_LOOP_DELAY;
move_selection = 1; //continue (move selection)
} else {
scroll_delay--; // wait
}
if (move_selection)
{
browser.selIndex++;
if (browser.selIndex == browser.numEntries)
browser.selIndex = browser.pageIndex = 0;
if ((browser.selIndex - browser.pageIndex) >= PAGESIZE)
browser.pageIndex += PAGESIZE;
redraw = 1;
move_selection = 0;
}
} // End of down
if ( ((p | ph) & PAD_BUTTON_UP) || ((wp | wh) & (WPAD_BUTTON_UP | WPAD_CLASSIC_BUTTON_UP)) || (gc_ay > PADCAL) || (wm_ay > PADCAL) )
{
if ( (p & PAD_BUTTON_UP) || (wp & (WPAD_BUTTON_UP | WPAD_CLASSIC_BUTTON_UP)) ) { /*** Button just pressed***/
scroll_delay = SCROLL_INITIAL_DELAY; // reset scroll delay.
move_selection = 1; //continue (move selection)
}
else if (scroll_delay == 0) { /*** Button is held ***/
scroll_delay = SCROLL_LOOP_DELAY;
move_selection = 1; //continue (move selection)
} else {
scroll_delay--; // wait
}
if (move_selection)
{
browser.selIndex--;
if (browser.selIndex < 0) {
browser.selIndex = browser.numEntries - 1;
browser.pageIndex = browser.selIndex - PAGESIZE + 1;
}
if (browser.selIndex < browser.pageIndex)
browser.pageIndex -= PAGESIZE;
if (browser.pageIndex < 0)
browser.pageIndex = 0;
redraw = 1;
move_selection = 0;
}
} // End of Up
if ( (p & PAD_BUTTON_LEFT) || (wp & (WPAD_BUTTON_LEFT | WPAD_CLASSIC_BUTTON_LEFT)) )
{
/*** Go back a page ***/
browser.selIndex -= PAGESIZE;
if (browser.selIndex < 0)
{
browser.selIndex = browser.numEntries - 1;
browser.pageIndex = browser.selIndex - PAGESIZE + 1;
}
if (browser.selIndex < browser.pageIndex)
browser.pageIndex -= PAGESIZE;
if (browser.pageIndex < 0)
browser.pageIndex = 0;
redraw = 1;
}
if ( (p & PAD_BUTTON_RIGHT) || (wp & (WPAD_BUTTON_RIGHT | WPAD_CLASSIC_BUTTON_RIGHT)) )
{
/*** Go forward a page ***/
browser.selIndex += PAGESIZE;
if (browser.selIndex > browser.numEntries - 1)
browser.selIndex = browser.pageIndex = 0;
if ((browser.selIndex - browser.pageIndex) >= PAGESIZE)
browser.pageIndex += PAGESIZE;
redraw = 1;
}
}
return 0;
}
/****************************************************************************
* OpenROM
* Opens device specified by method, displays a list of ROMS
***************************************************************************/
int
OpenROM (int method)
{
if(method == METHOD_AUTO)
method = autoLoadMethod();
if(ChangeInterface(method, NOTSILENT))
{
// change current dir to roms directory
switch(method)
{
case METHOD_DVD:
browser.dir[0] = 0;
browser.numEntries = ParseDVDdirectory(); // Parse root directory
SwitchDVDFolder(GCSettings.LoadFolder); // switch to ROM folder
break;
default:
sprintf(browser.dir, "/%s", GCSettings.LoadFolder);
browser.numEntries = ParseDirectory(); // Parse root directory
break;
}
if (browser.numEntries > 0)
{
// Select an entry
return FileSelector (method);
}
else
{
// no entries found
WaitPrompt ("No Files Found!");
return 0;
}
}
return 0;
}

View File

@ -3,19 +3,18 @@
* *
* Tantric September 2008 * Tantric September 2008
* *
* filebrowser.h * filesel.h
* *
* Generic file routines - reading, writing, browsing * Generic file routines - reading, writing, browsing
****************************************************************************/ ****************************************************************************/
#ifndef _FILEBROWSER_H_ #ifndef _NGCFILESEL_
#define _FILEBROWSER_H_ #define _NGCFILESEL_
#include <unistd.h> #include <unistd.h>
#include <gccore.h>
#define MAXJOLIET 255 #define MAXJOLIET 255
#define MAXDISPLAY 35 #define MAXDISPLAY 40
typedef struct typedef struct
{ {
@ -29,7 +28,6 @@ typedef struct
{ {
u64 offset; // DVD offset u64 offset; // DVD offset
unsigned int length; // file length unsigned int length; // file length
time_t mtime; // file modified time
char isdir; // 0 - file, 1 - directory char isdir; // 0 - file, 1 - directory
char filename[MAXJOLIET + 1]; // full filename char filename[MAXJOLIET + 1]; // full filename
char displayname[MAXDISPLAY + 1]; // name for browser display char displayname[MAXDISPLAY + 1]; // name for browser display
@ -38,23 +36,17 @@ typedef struct
extern BROWSERINFO browser; extern BROWSERINFO browser;
extern BROWSERENTRY * browserList; extern BROWSERENTRY * browserList;
extern char rootdir[10]; extern char rootdir[10];
extern char ROMFilename[512];
extern bool ROMLoaded;
extern char szpath[MAXPATHLEN]; extern char szpath[MAXPATHLEN];
extern bool inSz; extern bool inSz;
extern char ROMFilename[512];
bool MakeFilePath(char filepath[], int type, int method, char * filename = NULL, int filenum = -2); bool MakeFilePath(char filepath[], int type, int method);
int UpdateDirName(int method); int OpenROM (int method);
int OpenGameList();
int autoLoadMethod(); int autoLoadMethod();
int autoSaveMethod(bool silent); int autoSaveMethod(bool silent);
int FileSortCallback(const void *f1, const void *f2); int FileSortCallback(const void *f1, const void *f2);
void StripExt(char* returnstring, char * inputstring); void StripExt(char* returnstring, char * inputstring);
void ShortenFilename(char* returnstring, char * inputstring);
bool IsSz();
void ResetBrowser(); void ResetBrowser();
int BrowserLoadSz(int method);
int BrowserChangeFolder(int method);
int BrowserLoadFile(int method);
#endif #endif

Binary file not shown.

View File

@ -30,17 +30,234 @@
#include "gba/bios.h" #include "gba/bios.h"
#include "gba/GBAinline.h" #include "gba/GBAinline.h"
/*char DebugStr[50] = ""; char DebugStr[50] = "";
void DebugPrintf(const char *format, ...) { /*void DebugPrintf(const char *format, ...) {
va_list args; va_list args;
va_start( args, format ); va_start( args, format );
vsprintf( DebugStr, format, args ); vsprintf( DebugStr, format, args );
va_end( args ); va_end( args );
}*/ }*/
u32 MK1Input(unsigned short pad) {
u32 J = StandardMovement(pad);
u8 Health = gbReadMemory(0xc695);
static u8 OldHealth = 0;
// Rumble when they lose health!
if (Health < OldHealth)
systemGameRumble(5);
OldHealth = Health;
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
// Punch
if (wp->btns_h & WPAD_BUTTON_UP || wp->btns_h & WPAD_BUTTON_LEFT)
J |= VBA_BUTTON_B;
// Kick
if (wp->btns_h & WPAD_BUTTON_DOWN || wp->btns_h & WPAD_BUTTON_RIGHT)
J |= VBA_BUTTON_A;
// Block
if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z))
J |= VBA_BUTTON_A | VBA_BUTTON_B; // different from MK2
// Throw
if (wp->btns_h & WPAD_BUTTON_A)
J |= VBA_BUTTON_B | VBA_RIGHT; // CAKTODO check which way we are facing
// Pause
if (wp->btns_h & WPAD_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
// Start
if (wp->btns_h & WPAD_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Special move
if (wp->btns_h & WPAD_BUTTON_B)
{
// CAKTODO
}
#endif
return J;
}
u32 MK4Input(unsigned short pad)
{
u32 J = StandardMovement(pad);
u8 Health = 0;
static u8 OldHealth = 0;
// Rumble when they lose health!
if (Health < OldHealth)
systemGameRumble(20);
OldHealth = Health;
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
// Punch
if (wp->btns_h & WPAD_BUTTON_UP || wp->btns_h & WPAD_BUTTON_LEFT)
J |= VBA_BUTTON_B;
// Kick
if (wp->btns_h & WPAD_BUTTON_DOWN || wp->btns_h & WPAD_BUTTON_RIGHT)
J |= VBA_BUTTON_A;
// Block
if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z))
J |= VBA_BUTTON_START;
// Throw
if (wp->btns_h & WPAD_BUTTON_A)
J |= VBA_BUTTON_B | VBA_RIGHT; // CAKTODO check which way we are facing
// Pause
if (wp->btns_h & WPAD_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
// Start
if (wp->btns_h & WPAD_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Special move
if (wp->btns_h & WPAD_BUTTON_B)
{
// CAKTODO
}
#endif
return J;
}
u32 MKAInput(unsigned short pad)
{
u32 J = StandardMovement(pad);
u8 Health = 0;
static u8 OldHealth = 0;
// Rumble when they lose health!
if (Health < OldHealth)
systemGameRumble(20);
OldHealth = Health;
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
// Punch
if (wp->btns_h & WPAD_BUTTON_UP || wp->btns_h & WPAD_BUTTON_LEFT)
J |= VBA_BUTTON_B;
// Kick
if (wp->btns_h & WPAD_BUTTON_DOWN || wp->btns_h & WPAD_BUTTON_RIGHT)
J |= VBA_BUTTON_A;
// Block
if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z))
J |= VBA_BUTTON_R;
// Run (supposed to be change styles)
if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & WPAD_NUNCHUK_BUTTON_C))
J |= VBA_BUTTON_L;
// Throw
if (wp->btns_h & WPAD_BUTTON_A)
J |= VBA_RIGHT; // CAKTODO check which way we are facing
// Pause
if (wp->btns_h & WPAD_BUTTON_PLUS || wp->btns_h & WPAD_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
// Special move
if (wp->btns_h & WPAD_BUTTON_B)
{
// CAKTODO
}
#endif
return J;
}
u32 MKTEInput(unsigned short pad)
{
static u32 prevJ = 0, prevPrevJ = 0;
u32 J = StandardMovement(pad);
#ifdef HW_RVL
WPADData * wp = WPAD_Data(pad);
u8 Health;
u8 Side;
if (RomIdCode & 0xFFFFFF == MKDA)
{
Health = CPUReadByte(0x3000760); // 731 or 760
Side = CPUReadByte(0x3000747);
}
else
{
Health = CPUReadByte(0x3000761); // or 790
Side = CPUReadByte(0x3000777);
}
static u8 OldHealth = 0;
// Rumble when they lose health!
if (Health < OldHealth)
systemGameRumble(20);
OldHealth = Health;
u32 Forwards, Back;
if (Side == 0)
{
Forwards = VBA_RIGHT;
Back = VBA_LEFT;
}
else
{
Forwards = VBA_LEFT;
Back = VBA_RIGHT;
}
// Punch
if (wp->btns_h & WPAD_BUTTON_UP || wp->btns_h & WPAD_BUTTON_LEFT)
J |= VBA_BUTTON_B;
// Kick
if (wp->btns_h & WPAD_BUTTON_DOWN || wp->btns_h & WPAD_BUTTON_RIGHT)
J |= VBA_BUTTON_A;
// Block
if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & WPAD_NUNCHUK_BUTTON_Z))
J |= VBA_BUTTON_R;
// Change styles
if ((wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & WPAD_NUNCHUK_BUTTON_C))
J |= VBA_BUTTON_L;
// Throw
if (wp->btns_h & WPAD_BUTTON_A)
{
if ((prevJ & Forwards && prevJ & VBA_BUTTON_A && prevJ & VBA_BUTTON_B) || ((prevPrevJ & Forwards) && !(prevJ & Forwards)))
J |= Forwards | VBA_BUTTON_A | VBA_BUTTON_B; // R, R+1+2 = throw
else if (prevJ & Forwards)
{
J &= ~Forwards;
J &= ~VBA_BUTTON_A;
J &= ~VBA_BUTTON_B;
}
else
J |= Forwards;
}
// Pause
if (wp->btns_h & WPAD_BUTTON_MINUS)
J |= VBA_BUTTON_SELECT;
// Start
if (wp->btns_h & WPAD_BUTTON_PLUS)
J |= VBA_BUTTON_START;
// Special move
if (wp->btns_h & WPAD_BUTTON_B) {
// CAKTODO
}
// Speed
if (wp->btns_h & WPAD_BUTTON_1 || wp->btns_h & WPAD_BUTTON_2) {
J |= VBA_SPEED;
}
#endif
if ((J & 48) == 48)
J &= ~16;
if ((J & 192) == 192)
J &= ~128;
prevPrevJ = prevJ;
prevJ = J;
return J;
}
u32 LegoStarWars1Input(unsigned short pad) { u32 LegoStarWars1Input(unsigned short pad) {
u32 J = StandardMovement(pad) | DecodeGamecube(pad) | DPadWASD(pad); u32 J = StandardMovement(pad) | DecodeGamecube(pad) | DecodeKeyboard(pad);
// Rumble when they lose health! // Rumble when they lose health!
u8 Health = 0; u8 Health = 0;
static u8 OldHealth = 0; static u8 OldHealth = 0;
@ -49,14 +266,6 @@ u32 LegoStarWars1Input(unsigned short pad) {
OldHealth = Health; OldHealth = Health;
#ifdef HW_RVL #ifdef HW_RVL
if (DownUsbKeys[KB_ENTER]) J |= VBA_BUTTON_START; // start
if (DownUsbKeys[KB_K] || DownUsbKeys[KB_LCTRL]) J |= VBA_BUTTON_SELECT; // change chars
if (DownUsbKeys[KB_U]) J |= VBA_BUTTON_A; // jump
if (DownUsbKeys[KB_H]) J |= VBA_BUTTON_B; // attack
if (DownUsbKeys[KB_J]) J |= VBA_BUTTON_R; // force power, special ability
if (DownUsbKeys[KB_I]) J |= VBA_BUTTON_L; // build, use force (supposed to be J too)
if (DownUsbKeys[KB_SPACE]) J |= VBA_SPEED; // fast forward
WPADData * wp = WPAD_Data(pad); WPADData * wp = WPAD_Data(pad);
// Start/Select // Start/Select
@ -95,7 +304,7 @@ u32 LegoStarWars1Input(unsigned short pad) {
} }
u32 LegoStarWars2Input(unsigned short pad) { u32 LegoStarWars2Input(unsigned short pad) {
u32 J = StandardMovement(pad) | DecodeGamecube(pad) | DPadWASD(pad); u32 J = StandardMovement(pad) | DecodeGamecube(pad) | DecodeKeyboard(pad);
// Rumble when they lose health! // Rumble when they lose health!
u8 Health = 0; u8 Health = 0;
static u8 OldHealth = 0; static u8 OldHealth = 0;
@ -104,14 +313,6 @@ u32 LegoStarWars2Input(unsigned short pad) {
OldHealth = Health; OldHealth = Health;
#ifdef HW_RVL #ifdef HW_RVL
if (DownUsbKeys[KB_ENTER]) J |= VBA_BUTTON_START; // start
if (DownUsbKeys[KB_K] || DownUsbKeys[KB_LCTRL]) J |= VBA_BUTTON_SELECT; // change chars
if (DownUsbKeys[KB_U]) J |= VBA_BUTTON_A; // jump
if (DownUsbKeys[KB_H]) J |= VBA_BUTTON_B; // attack
if (DownUsbKeys[KB_J]) J |= VBA_BUTTON_L; // force power, special ability
if (DownUsbKeys[KB_I]) J |= VBA_BUTTON_R; // build, use force (supposed to be J too)
if (DownUsbKeys[KB_SPACE]) J |= VBA_SPEED; // fast forward
WPADData * wp = WPAD_Data(pad); WPADData * wp = WPAD_Data(pad);
// Start/Select // Start/Select

View File

@ -20,14 +20,13 @@ extern "C" {
#include "../sz/7zExtract.h" #include "../sz/7zExtract.h"
} }
#include "vba.h"
#include "dvd.h" #include "dvd.h"
#include "networkop.h" #include "networkop.h"
#include "fileop.h" #include "fileop.h"
#include "filebrowser.h"
#include "video.h" #include "video.h"
#include "menu.h" #include "menudraw.h"
#include "gcunzip.h" #include "gcunzip.h"
#include "vba.h"
#define ZIPCHUNK 2048 #define ZIPCHUNK 2048
@ -147,7 +146,7 @@ UnZipBuffer (unsigned char *outbuffer, int method)
res = inflateInit2 (&zs, -MAX_WBITS); res = inflateInit2 (&zs, -MAX_WBITS);
if (res != Z_OK) if (res != Z_OK)
goto done; return 0;
/*** Set ZipChunk for first pass ***/ /*** Set ZipChunk for first pass ***/
zipoffset = zipoffset =
@ -171,7 +170,8 @@ UnZipBuffer (unsigned char *outbuffer, int method)
if (res == Z_MEM_ERROR) if (res == Z_MEM_ERROR)
{ {
goto done; inflateEnd (&zs);
return 0;
} }
have = ZIPCHUNK - zs.avail_out; have = ZIPCHUNK - zs.avail_out;
@ -199,20 +199,23 @@ UnZipBuffer (unsigned char *outbuffer, int method)
break; break;
} }
if(sizeread <= 0) if(sizeread <= 0)
goto done; // read failure break; // read failure
ShowProgress ("Loading...", bufferoffset, pkzip.uncompressedSize); ShowProgress ("Loading...", bufferoffset, pkzip.uncompressedSize);
} }
while (res != Z_STREAM_END); while (res != Z_STREAM_END);
done:
inflateEnd (&zs); inflateEnd (&zs);
CancelAction();
if (res == Z_STREAM_END) if (res == Z_STREAM_END)
return pkzip.uncompressedSize; {
else if (pkzip.uncompressedSize == (u32) bufferoffset)
return 0; return bufferoffset;
else
return pkzip.uncompressedSize;
}
return 0;
} }
/**************************************************************************** /****************************************************************************
@ -245,7 +248,7 @@ GetFirstZipFilename (int method)
} }
else else
{ {
ErrorPrompt("Error - Invalid ZIP file!"); WaitPrompt("Error - Invalid ZIP file!");
} }
} }
@ -315,7 +318,7 @@ Is7ZipFile (char *buffer)
// display an error message // display an error message
static void SzDisplayError(SZ_RESULT res) static void SzDisplayError(SZ_RESULT res)
{ {
ErrorPrompt(szerrormsg[(res - 1)]); WaitPrompt(szerrormsg[(res - 1)]);
} }
// function used by the 7zip SDK to read data from SD/USB/DVD/SMB // function used by the 7zip SDK to read data from SD/USB/DVD/SMB
@ -470,7 +473,7 @@ int SzParse(char * filepath, int method)
if(!newBrowserList) // failed to allocate required memory if(!newBrowserList) // failed to allocate required memory
{ {
ResetBrowser(); ResetBrowser();
ErrorPrompt("Out of memory: too many files!"); WaitPrompt("Out of memory: too many files!");
nbfiles = 0; nbfiles = 0;
break; break;
} }
@ -482,9 +485,7 @@ int SzParse(char * filepath, int method)
// parse information about this file to the dvd file list structure // parse information about this file to the dvd file list structure
strncpy(browserList[SzJ].filename, SzF->Name, MAXJOLIET); // copy joliet name (useless...) strncpy(browserList[SzJ].filename, SzF->Name, MAXJOLIET); // copy joliet name (useless...)
char tmpname[MAXJOLIET+1] = ""; strncpy(browserList[SzJ].displayname, SzF->Name, MAXDISPLAY); // crop name for display
ShortenFilename(tmpname, browserList[SzJ].filename);
strncpy(browserList[SzJ].displayname, tmpname, MAXDISPLAY); // crop name for display
browserList[SzJ].length = SzF->Size; // filesize browserList[SzJ].length = SzF->Size; // filesize
browserList[SzJ].offset = SzI; // the extraction function identifies the file with this number browserList[SzJ].offset = SzI; // the extraction function identifies the file with this number
browserList[SzJ].isdir = 0; // only files will be displayed (-> no flags) browserList[SzJ].isdir = 0; // only files will be displayed (-> no flags)
@ -553,8 +554,6 @@ int SzExtractFile(int i, unsigned char *buffer)
// close 7Zip archive and free memory // close 7Zip archive and free memory
SzClose(); SzClose();
CancelAction();
// check for errors // check for errors
if(SzRes != SZ_OK) if(SzRes != SZ_OK)
{ {

View File

@ -1,35 +1,15 @@
/*!\mainpage libwiigui Documentation /****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
* *
* \section Introduction * Tantric February 2009
* libwiigui is a GUI library for the Wii, created to help structure the
* design of a complicated GUI interface, and to enable an author to create
* a sophisticated, feature-rich GUI. It was originally conceived and written
* after I started to design a GUI for Snes9x GX, and found libwiisprite and
* GRRLIB inadequate for the purpose. It uses GX for drawing, and makes use
* of PNGU for displaying images and FreeTypeGX for text. It was designed to
* be flexible and is easy to modify - don't be afraid to change the way it
* works or expand it to suit your GUI's purposes! If you do, and you think
* your changes might benefit others, please share them so they might be
* added to the project!
* *
* \section Quickstart * gui.h
* Start from the supplied template example. For more advanced uses, see the
* source code for Snes9x GX, FCE Ultra GX, and Visual Boy Advance GX.
* \section Contact
* If you have any suggestions for the library or documentation, or want to
* contribute, please visit the libwiigui website:
* http://code.google.com/p/libwiigui/
* \section Credits
* This library was wholly designed and written by Tantric. Thanks to the
* authors of PNGU and FreeTypeGX, of which this library makes use. Thanks
* also to the authors of GRRLIB and libwiisprite for laying the foundations.
* *
*/ * GUI class definitions
***************************************************************************/
#ifndef LIBWIIGUI_H #ifndef GUI_H
#define LIBWIIGUI_H #define GUI_H
#include <gccore.h> #include <gccore.h>
#include <malloc.h> #include <malloc.h>
@ -37,25 +17,38 @@
#include <string.h> #include <string.h>
#include <vector> #include <vector>
#include <math.h> #include <math.h>
#include <asndlib.h> #include <wiiuse/wpad.h>
#include <mp3player.h>
#include "pngu/pngu.h" #include "pngu/pngu.h"
#include "FreeTypeGX.h" #include "FreeTypeGX.h"
#include "vba.h" #include "vba.h"
#include "video.h" #include "video.h"
#include "input.h"
#include "filelist.h" #include "filelist.h"
#include "fileop.h" #include "fileop.h"
#include "oggplayer.h" #include "menu.h"
#include "input.h"
#define PI 3.14159265f
#define PADCAL 50
#define SCROLL_INITIAL_DELAY 20 #define SCROLL_INITIAL_DELAY 20
#define SCROLL_LOOP_DELAY 3 #define SCROLL_LOOP_DELAY 3
#define PAGESIZE 8
#define SAVELISTSIZE 6 #define SAVELISTSIZE 6
#define MAX_SAVES 20
#define MAX_OPTIONS 30
typedef void (*UpdateCallback)(void * e); typedef void (*UpdateCallback)(void * e);
typedef struct _paddata {
u16 btns_d;
u16 btns_u;
u16 btns_h;
s8 stickX;
s8 stickY;
s8 substickX;
s8 substickY;
u8 triggerL;
u8 triggerR;
} PADData;
enum enum
{ {
ALIGN_LEFT, ALIGN_LEFT,
@ -76,15 +69,9 @@ enum
enum enum
{ {
SOUND_PCM, TRIGGER_SIMPLE,
SOUND_OGG TRIGGER_BUTTON_ONLY,
}; TRIGGER_BUTTON_ONLY_IN_FOCUS
enum
{
IMAGE_TEXTURE,
IMAGE_COLOR,
IMAGE_DATA
}; };
#define EFFECT_SLIDE_TOP 1 #define EFFECT_SLIDE_TOP 1
@ -97,696 +84,146 @@ enum
#define EFFECT_SCALE 128 #define EFFECT_SCALE 128
#define EFFECT_COLOR_TRANSITION 256 #define EFFECT_COLOR_TRANSITION 256
//!Sound conversion and playback. A wrapper for other sound libraries - ASND, libmad, ltremor, etc enum
{
ON_CLICK,
ON_OVER
};
class GuiSound class GuiSound
{ {
public: public:
//!Constructor GuiSound(const u8 * s, int l);
//!\param s Pointer to the sound data
//!\param l Length of sound data
//!\param t Sound format type (SOUND_PCM or SOUND_OGG)
GuiSound(const u8 * s, int l, int t);
//!Destructor
~GuiSound(); ~GuiSound();
//!Start sound playback
void Play(); void Play();
//!Stop sound playback
void Stop();
//!Pause sound playback
void Pause();
//!Resume sound playback
void Resume();
//!Checks if the sound is currently playing
//!\return true if sound is playing, false otherwise
bool IsPlaying();
//!Set sound volume
//!\param v Sound volume (0-100)
void SetVolume(int v);
//!Set the sound to loop playback (only applies to OGG)
//!\param l Loop (true to loop)
void SetLoop(bool l);
protected: protected:
const u8 * sound; //!< Pointer to the sound data const u8 * sound;
int type; //!< Sound format type (SOUND_PCM or SOUND_OGG) s32 length;
s32 length; //!< Length of sound data };
s32 voice; //!< Currently assigned ASND voice channel
s32 volume; //!< Sound volume (0-100) class GuiTrigger
bool loop; //!< Loop sound playback {
public:
GuiTrigger();
~GuiTrigger();
void SetSimpleTrigger(s32 ch, u32 wiibtns, u16 gcbtns);
void SetButtonOnlyTrigger(s32 ch, u32 wiibtns, u16 gcbtns);
void SetButtonOnlyInFocusTrigger(s32 ch, u32 wiibtns, u16 gcbtns);
s8 WPAD_Stick(u8 right, int axis);
bool Left();
bool Right();
bool Up();
bool Down();
u8 type;
s32 chan;
WPADData wpad;
PADData pad;
}; };
//!Primary Gui class
class GuiElement class GuiElement
{ {
public: public:
//!Constructor
GuiElement(); GuiElement();
//!Destructor
~GuiElement(); ~GuiElement();
//!Set the element's parent
//!\param e Pointer to parent element
void SetParent(GuiElement * e); void SetParent(GuiElement * e);
//!Gets the current leftmost coordinate of the element
//!Considers horizontal alignment, x offset, width, and parent element's GetLeft() / GetWidth() values
//!\return left coordinate
int GetLeft(); int GetLeft();
//!Gets the current topmost coordinate of the element
//!Considers vertical alignment, y offset, height, and parent element's GetTop() / GetHeight() values
//!\return top coordinate
int GetTop(); int GetTop();
//!Gets the current width of the element. Does not currently consider the scale
//!\return width
int GetWidth(); int GetWidth();
//!Gets the height of the element. Does not currently consider the scale
//!\return height
int GetHeight(); int GetHeight();
//!Sets the size (width/height) of the element
//!\param w Width of element
//!\param h Height of element
void SetSize(int w, int h); void SetSize(int w, int h);
//!Checks whether or not the element is visible
//!\return true if visible, false otherwise
bool IsVisible(); bool IsVisible();
//!Checks whether or not the element is selectable
//!\return true if selectable, false otherwise
bool IsSelectable(); bool IsSelectable();
//!Checks whether or not the element is clickable
//!\return true if clickable, false otherwise
bool IsClickable(); bool IsClickable();
//!Sets whether or not the element is selectable
//!\param s Selectable
void SetSelectable(bool s); void SetSelectable(bool s);
//!Sets whether or not the element is clickable
//!\param c Clickable
void SetClickable(bool c); void SetClickable(bool c);
//!Gets the element's current state
//!\return state
int GetState(); int GetState();
//!Sets the element's alpha value void SetVisible(bool v);
//!\param a alpha value
void SetAlpha(int a); void SetAlpha(int a);
//!Gets the element's alpha value
//!Considers alpha, alphaDyn, and the parent element's GetAlpha() value
//!\return alpha
int GetAlpha(); int GetAlpha();
//!Sets the element's scale
//!\param s scale (1 is 100%)
void SetScale(float s); void SetScale(float s);
//!Gets the element's current scale
//!Considers scale, scaleDyn, and the parent element's GetScale() value
float GetScale(); float GetScale();
//!Set a new GuiTrigger for the element
//!\param t Pointer to GuiTrigger
void SetTrigger(GuiTrigger * t); void SetTrigger(GuiTrigger * t);
//!\overload
//!\param i Index of trigger array to set
//!\param t Pointer to GuiTrigger
void SetTrigger(u8 i, GuiTrigger * t); void SetTrigger(u8 i, GuiTrigger * t);
//!Checks whether rumble was requested by the element
//!\return true is rumble was requested, false otherwise
bool Rumble();
//!Sets whether or not the element is requesting a rumble event
//!\param r true if requesting rumble, false if not
void SetRumble(bool r);
//!Set an effect for the element
//!\param e Effect to enable
//!\param a Amount of the effect (usage varies on effect)
//!\param t Target amount of the effect (usage varies on effect)
void SetEffect(int e, int a, int t=0); void SetEffect(int e, int a, int t=0);
//!Sets an effect to be enabled on wiimote cursor over
//!\param e Effect to enable
//!\param a Amount of the effect (usage varies on effect)
//!\param t Target amount of the effect (usage varies on effect)
void SetEffectOnOver(int e, int a, int t=0); void SetEffectOnOver(int e, int a, int t=0);
//!Shortcut to SetEffectOnOver(EFFECT_SCALE, 4, 110)
void SetEffectGrow(); void SetEffectGrow();
//!Gets the current element effects
//!\return element effects
int GetEffect(); int GetEffect();
//!Checks whether the specified coordinates are within the element's boundaries
//!\param x X coordinate
//!\param y Y coordinate
//!\return true if contained within, false otherwise
bool IsInside(int x, int y); bool IsInside(int x, int y);
//!Sets the element's position
//!\param x X coordinate
//!\param y Y coordinate
void SetPosition(int x, int y); void SetPosition(int x, int y);
//!Updates the element's effects (dynamic values)
//!Called by Draw(), used for animation purposes
void UpdateEffects(); void UpdateEffects();
//!Sets a function to called after after Update()
//!Callback function can be used to response to changes in the state of the element, and/or update the element's attributes
void SetUpdateCallback(UpdateCallback u); void SetUpdateCallback(UpdateCallback u);
//!Checks whether the element is in focus
//!\return true if element is in focus, false otherwise
int IsFocused(); int IsFocused();
//!Sets the element's visibility
//!\param v Visibility (true = visible)
virtual void SetVisible(bool v);
//!Sets the element's focus
//!\param v Focus (true = in focus)
virtual void SetFocus(int f); virtual void SetFocus(int f);
//!Sets the element's state
//!\param v State (STATE_DEFAULT, STATE_SELECTED, STATE_CLICKED, STATE_DISABLED)
virtual void SetState(int s); virtual void SetState(int s);
//!Resets the element's state to STATE_DEFAULT
virtual void ResetState(); virtual void ResetState();
//!Gets whether or not the element is in STATE_SELECTED
//!\return true if selected, false otherwise
virtual int GetSelected(); virtual int GetSelected();
//!Sets the element's alignment respective to its parent element
//!\param hor Horizontal alignment (ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTRE)
//!\param vert Vertical alignment (ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE)
virtual void SetAlignment(int hor, int vert); virtual void SetAlignment(int hor, int vert);
//!Called constantly to allow the element to respond to the current input data
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
virtual void Update(GuiTrigger * t); virtual void Update(GuiTrigger * t);
//!Called constantly to redraw the element
virtual void Draw(); virtual void Draw();
protected: protected:
bool visible; //!< Visibility of the element. If false, Draw() is skipped bool visible;
int focus; //!< Element focus (-1 = focus disabled, 0 = not focused, 1 = focused) int focus; // -1 = cannot focus, 0 = not focused, 1 = focused
int width; //!< Element width int width;
int height; //!< Element height int height;
int xoffset; //!< Element X offset int xoffset;
int yoffset; //!< Element Y offset int yoffset;
int xoffsetDyn; //!< Element X offset, dynamic (added to xoffset value for animation effects) int xoffsetDyn;
int yoffsetDyn; //!< Element Y offset, dynamic (added to yoffset value for animation effects) int yoffsetDyn;
int alpha; //!< Element alpha value (0-255) int alpha;
f32 scale; //!< Element scale (1 = 100%) f32 scale;
int alphaDyn; //!< Element alpha, dynamic (multiplied by alpha value for blending/fading effects) int alphaDyn;
f32 scaleDyn; //!< Element scale, dynamic (multiplied by alpha value for blending/fading effects) f32 scaleDyn;
bool rumble; //!< Wiimote rumble (on/off) - set to on when this element requests a rumble event int effects;
int effects; //!< Currently enabled effect(s). 0 when no effects are enabled int effectAmount;
int effectAmount; //!< Effect amount. Used by different effects for different purposes int effectTarget;
int effectTarget; //!< Effect target amount. Used by different effects for different purposes int effectsOver;
int effectsOver; //!< Effects to enable when wiimote cursor is over this element. Copied to effects variable on over event int effectAmountOver;
int effectAmountOver; //!< EffectAmount to set when wiimote cursor is over this element int effectTargetOver;
int effectTargetOver; //!< EffectTarget to set when wiimote cursor is over this element int alignmentHor; // LEFT, RIGHT, CENTRE
int alignmentHor; //!< Horizontal element alignment, respective to parent element (LEFT, RIGHT, CENTRE) int alignmentVert; // TOP, BOTTOM, MIDDLE
int alignmentVert; //!< Horizontal element alignment, respective to parent element (TOP, BOTTOM, MIDDLE) int state; // DEFAULT, SELECTED, CLICKED, DISABLED
int state; //!< Element state (DEFAULT, SELECTED, CLICKED, DISABLED) bool selectable; // is SELECTED a valid state?
bool selectable; //!< Whether or not this element selectable (can change to SELECTED state) bool clickable; // is CLICKED a valid state?
bool clickable; //!< Whether or not this element is clickable (can change to CLICKED state) GuiTrigger * trigger[2];
GuiTrigger * trigger[2]; //!< GuiTriggers (input actions) that this element responds to GuiElement * parentElement;
GuiElement * parentElement; //!< Parent element UpdateCallback updateCB;
UpdateCallback updateCB; //!< Callback function to call when this element is updated
}; };
//!Allows GuiElements to be grouped together into a "window"
class GuiWindow : public GuiElement
{
public:
//!Constructor
GuiWindow();
//!\overload
//!\param w Width of window
//!\param h Height of window
GuiWindow(int w, int h);
//!Destructor
~GuiWindow();
//!Appends a GuiElement to the GuiWindow
//!\param e The GuiElement to append. If it is already in the GuiWindow, it is removed first
void Append(GuiElement* e);
//!Inserts a GuiElement into the GuiWindow at the specified index
//!\param e The GuiElement to insert. If it is already in the GuiWindow, it is removed first
//!\param i Index in which to insert the element
void Insert(GuiElement* e, u32 i);
//!Removes the specified GuiElement from the GuiWindow
//!\param e GuiElement to be removed
void Remove(GuiElement* e);
//!Removes all GuiElements
void RemoveAll();
//!Returns the GuiElement at the specified index
//!\param index The index of the element
//!\return A pointer to the element at the index, NULL on error (eg: out of bounds)
GuiElement* GetGuiElementAt(u32 index) const;
//!Returns the size of the list of elements
//!\return The size of the current element list
u32 GetSize();
//!Sets the visibility of the window
//!\param v visibility (true = visible)
void SetVisible(bool v);
//!Resets the window's state to STATE_DEFAULT
void ResetState();
//!Sets the window's state
//!\param s State
void SetState(int s);
//!Gets the index of the GuiElement inside the window that is currently selected
//!\return index of selected GuiElement
int GetSelected();
//!Sets the window focus
//!\param f Focus
void SetFocus(int f);
//!Change the focus to the specified element
//!This is intended for the primary GuiWindow only
//!\param e GuiElement that should have focus
void ChangeFocus(GuiElement * e);
//!Changes window focus to the next focusable window or element
//!If no element is in focus, changes focus to the first available element
//!If B or 1 button is pressed, changes focus to the next available element
//!This is intended for the primary GuiWindow only
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
void ToggleFocus(GuiTrigger * t);
//!Moves the selected element to the element to the left or right
//!\param d Direction to move (-1 = left, 1 = right)
void MoveSelectionHor(int d);
//!Moves the selected element to the element above or below
//!\param d Direction to move (-1 = up, 1 = down)
void MoveSelectionVert(int d);
//!Draws all the elements in this GuiWindow
void Draw();
//!Updates the window and all elements contains within
//!Allows the GuiWindow and all elements to respond to the input data specified
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
void Update(GuiTrigger * t);
protected:
std::vector<GuiElement*> _elements; //!< Contains all elements within the GuiWindow
};
//!Converts image data into GX-useable RGBA8
//!Currently designed for use only with PNG files
class GuiImageData class GuiImageData
{ {
public: public:
//!Constructor
//!Converts the image data to RGBA8 - expects PNG format
//!\param i Image data
GuiImageData(const u8 * i); GuiImageData(const u8 * i);
//!Destructor
~GuiImageData(); ~GuiImageData();
//!Gets a pointer to the image data
//!\return pointer to image data
u8 * GetImage(); u8 * GetImage();
//!Gets the image width
//!\return image width
int GetWidth(); int GetWidth();
//!Gets the image height
//!\return image height
int GetHeight(); int GetHeight();
protected: protected:
u8 * data; //!< Image data u8 * data;
int height; //!< Height of image int height;
int width; //!< Width of image int width;
}; };
//!Display, manage, and manipulate images in the Gui
class GuiImage : public GuiElement class GuiImage : public GuiElement
{ {
public: public:
//!Constructor
//!\param img Pointer to GuiImageData element
GuiImage(GuiImageData * img); GuiImage(GuiImageData * img);
//!\overload
//!Sets up a new image from the image data specified
//!\param img
//!\param w Image width
//!\param h Image height
GuiImage(u8 * img, int w, int h); GuiImage(u8 * img, int w, int h);
//!\overload
//!Creates an image filled with the specified color
//!\param w Image width
//!\param h Image height
//!\param c Image color
GuiImage(int w, int h, GXColor c); GuiImage(int w, int h, GXColor c);
//!Destructor
~GuiImage(); ~GuiImage();
//!Sets the image rotation angle for drawing
//!\param a Angle (in degrees)
void SetAngle(float a); void SetAngle(float a);
//!Sets the number of times to draw the image horizontally
//!\param t Number of times to draw the image
void SetTile(int t); void SetTile(int t);
//!Constantly called to draw the image
void Draw(); void Draw();
//!Gets the image data
//!\return pointer to image data
u8 * GetImage(); u8 * GetImage();
//!Sets up a new image using the GuiImageData object specified
//!\param img Pointer to GuiImageData object
void SetImage(GuiImageData * img); void SetImage(GuiImageData * img);
//!\overload
//!\param img Pointer to image data
//!\param w Width
//!\param h Height
void SetImage(u8 * img, int w, int h); void SetImage(u8 * img, int w, int h);
//!Gets the pixel color at the specified coordinates of the image
//!\param x X coordinate
//!\param y Y coordinate
GXColor GetPixel(int x, int y); GXColor GetPixel(int x, int y);
//!Sets the pixel color at the specified coordinates of the image
//!\param x X coordinate
//!\param y Y coordinate
//!\param color Pixel color
void SetPixel(int x, int y, GXColor color); void SetPixel(int x, int y, GXColor color);
//!Directly modifies the image data to create a color-striped effect void Stripe(int s);
//!Alters the RGB values by the specified amount
//!\param s Amount to increment/decrement the RGB values in the image
void ColorStripe(int s);
//!Sets a stripe effect on the image, overlaying alpha blended rectangles
//!Does not alter the image data
//!\param s Alpha amount to draw over the image
void SetStripe(int s);
protected: protected:
int imgType; //!< Type of image data (IMAGE_TEXTURE, IMAGE_COLOR, IMAGE_DATA) u8 * image;
u8 * image; //!< Poiner to image data. May be shared with GuiImageData data f32 imageangle;
f32 imageangle; //!< Angle to draw the image int tile;
int tile; //!< Number of times to draw (tile) the image horizontally
int stripe; //!< Alpha value (0-255) to apply a stripe effect to the texture
};
//!Display, manage, and manipulate text in the Gui
class GuiText : public GuiElement
{
public:
//!Constructor
//!\param t Text
//!\param s Font size
//!\param c Font color
GuiText(const char * t, int s, GXColor c);
//!\overload
//!\Assumes SetPresets() has been called to setup preferred text attributes
//!\param t Text
GuiText(const char * t);
//!Destructor
~GuiText();
//!Sets the text of the GuiText element
//!\param t Text
void SetText(const char * t);
//!Sets up preset values to be used by GuiText(t)
//!Useful when printing multiple text elements, all with the same attributes set
//!\param sz Font size
//!\param c Font color
//!\param w Maximum width of texture image (for text wrapping)
//!\param s Font size
//!\param h Text alignment (horizontal)
//!\param v Text alignment (vertical)
void SetPresets(int sz, GXColor c, int w, u16 s, int h, int v);
//!Sets the font size
//!\param s Font size
void SetFontSize(int s);
//!Sets the maximum width of the drawn texture image
//!If the text exceeds this, it is wrapped to the next line
//!\param w Maximum width
void SetMaxWidth(int w);
//!Sets the font color
//!\param c Font color
void SetColor(GXColor c);
//!Sets the FreeTypeGX style attributes
//!\param s Style attributes
void SetStyle(u16 s);
//!Sets the text alignment
//!\param hor Horizontal alignment (ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTRE)
//!\param vert Vertical alignment (ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE)
void SetAlignment(int hor, int vert);
//!Constantly called to draw the text
void Draw();
protected:
wchar_t* text; //!< Unicode text value
int size; //!< Font size
int maxWidth; //!< Maximum width of the generated text object (for text wrapping)
u16 style; //!< FreeTypeGX style attributes
GXColor color; //!< Font color
};
//!Display, manage, and manipulate buttons in the Gui
//!Buttons can have images, icons, text, and sound set (all of which are optional)
class GuiButton : public GuiElement
{
public:
//!Constructor
//!\param w Width
//!\param h Height
GuiButton(int w, int h);
//!Destructor
~GuiButton();
//!Sets the button's image
//!\param i Pointer to GuiImage object
void SetImage(GuiImage* i);
//!Sets the button's image on over
//!\param i Pointer to GuiImage object
void SetImageOver(GuiImage* i);
//!Sets the button's icon
//!\param i Pointer to GuiImage object
void SetIcon(GuiImage* i);
//!Sets the button's icon on over
//!\param i Pointer to GuiImage object
void SetIconOver(GuiImage* i);
//!Sets the button's label
//!\param t Pointer to GuiText object
void SetLabel(GuiText* t);
//!\overload
//!\param t Pointer to GuiText object
//!\param n Index of label to set
void SetLabel(GuiText* t, int n);
//!Sets the button's label on over (eg: different colored text)
//!\param t Pointer to GuiText object
void SetLabelOver(GuiText* t);
//!\overload
//!\param t Pointer to GuiText object
//!\param n Index of label to set
void SetLabelOver(GuiText* t, int n);
//!Sets the sound to play on over
//!\param s Pointer to GuiSound object
void SetSoundOver(GuiSound * s);
//!Sets the sound to play on click
//!\param s Pointer to GuiSound object
void SetSoundClick(GuiSound * s);
//!Constantly called to draw the GuiButton
void Draw();
//!Constantly called to allow the GuiButton to respond to updated input data
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
void Update(GuiTrigger * t);
protected:
GuiImage * image; //!< Button image
GuiImage * imageOver; //!< Button image on wiimote cursor over
GuiImage * icon; //!< Button icon (drawn after button image)
GuiImage * iconOver; //!< Button icon on wiimote cursor over
GuiText * label[3]; //!< Label(s) to display
GuiText * labelOver[3]; //!< Label(s) to display on wiimote cursor over
GuiSound * soundOver; //!< Sound to play on wiimote cursor over
GuiSound * soundClick; //!< Sound to play on click
};
//!Display a list of files
class GuiFileBrowser : public GuiElement
{
public:
GuiFileBrowser(int w, int h);
~GuiFileBrowser();
void ResetState();
void SetFocus(int f);
void Draw();
void TriggerUpdate();
void Update(GuiTrigger * t);
GuiButton * gameList[PAGESIZE];
protected:
int selectedItem;
bool listChanged;
GuiText * gameListText[PAGESIZE];
GuiImage * gameListBg[PAGESIZE];
GuiImage * gameListFolder[PAGESIZE];
GuiButton * arrowUpBtn;
GuiButton * arrowDownBtn;
GuiButton * scrollbarBoxBtn;
GuiImage * bgGameSelectionImg;
GuiImage * scrollbarImg;
GuiImage * arrowDownImg;
GuiImage * arrowDownOverImg;
GuiImage * arrowUpImg;
GuiImage * arrowUpOverImg;
GuiImage * scrollbarBoxImg;
GuiImage * scrollbarBoxOverImg;
GuiImageData * bgGameSelection;
GuiImageData * bgGameSelectionEntry;
GuiImageData * gameFolder;
GuiImageData * scrollbar;
GuiImageData * arrowDown;
GuiImageData * arrowDownOver;
GuiImageData * arrowUp;
GuiImageData * arrowUpOver;
GuiImageData * scrollbarBox;
GuiImageData * scrollbarBoxOver;
GuiSound * btnSoundOver;
GuiSound * btnSoundClick;
GuiTrigger * trigA;
};
typedef struct _optionlist {
int length;
char name[MAX_OPTIONS][150];
char value[MAX_OPTIONS][150];
} OptionList;
//!Display a list of menu options
class GuiOptionBrowser : public GuiElement
{
public:
GuiOptionBrowser(int w, int h, OptionList * l);
~GuiOptionBrowser();
void SetCol2Position(int x);
int FindMenuItem(int c, int d);
int GetClickedOption();
void ResetState();
void SetFocus(int f);
void Draw();
void Update(GuiTrigger * t);
GuiText * optionVal[PAGESIZE];
protected:
int selectedItem;
int listOffset;
OptionList * options;
int optionIndex[PAGESIZE];
GuiButton * optionBtn[PAGESIZE];
GuiText * optionTxt[PAGESIZE];
GuiImage * optionBg[PAGESIZE];
GuiButton * arrowUpBtn;
GuiButton * arrowDownBtn;
GuiButton * scrollbarBoxBtn;
GuiImage * bgOptionsImg;
GuiImage * scrollbarImg;
GuiImage * arrowDownImg;
GuiImage * arrowDownOverImg;
GuiImage * arrowUpImg;
GuiImage * arrowUpOverImg;
GuiImage * scrollbarBoxImg;
GuiImage * scrollbarBoxOverImg;
GuiImageData * bgOptions;
GuiImageData * bgOptionsEntry;
GuiImageData * scrollbar;
GuiImageData * arrowDown;
GuiImageData * arrowDownOver;
GuiImageData * arrowUp;
GuiImageData * arrowUpOver;
GuiImageData * scrollbarBox;
GuiImageData * scrollbarBoxOver;
GuiSound * btnSoundOver;
GuiSound * btnSoundClick;
GuiTrigger * trigA;
};
typedef struct _savelist {
int length;
char filename[MAX_SAVES][256];
GuiImageData * previewImg[MAX_SAVES];
char date[MAX_SAVES][20];
char time[MAX_SAVES][10];
int type[MAX_SAVES];
int files[2][100];
} SaveList;
//!Display a list of game save files, with screenshots and file information
class GuiSaveBrowser : public GuiElement
{
public:
GuiSaveBrowser(int w, int h, SaveList * l, int a);
~GuiSaveBrowser();
int GetClickedSave();
void ResetState();
void SetFocus(int f);
void Draw();
void Update(GuiTrigger * t);
protected:
int selectedItem;
int listOffset;
int action;
SaveList * saves;
GuiButton * saveBtn[SAVELISTSIZE];
GuiText * saveDate[SAVELISTSIZE];
GuiText * saveTime[SAVELISTSIZE];
GuiText * saveType[SAVELISTSIZE];
GuiImage * saveBgImg[SAVELISTSIZE];
GuiImage * saveBgOverImg[SAVELISTSIZE];
GuiImage * savePreviewImg[SAVELISTSIZE];
GuiButton * arrowUpBtn;
GuiButton * arrowDownBtn;
GuiButton * scrollbarBoxBtn;
GuiImage * scrollbarImg;
GuiImage * arrowDownImg;
GuiImage * arrowDownOverImg;
GuiImage * arrowUpImg;
GuiImage * arrowUpOverImg;
GuiImage * scrollbarBoxImg;
GuiImage * scrollbarBoxOverImg;
GuiImageData * gameSave;
GuiImageData * gameSaveOver;
GuiImageData * gameSaveBlank;
GuiImageData * scrollbar;
GuiImageData * arrowDown;
GuiImageData * arrowDownOver;
GuiImageData * arrowUp;
GuiImageData * arrowUpOver;
GuiImageData * scrollbarBox;
GuiImageData * scrollbarBoxOver;
GuiSound * btnSoundOver;
GuiSound * btnSoundClick;
GuiTrigger * trigA;
};
typedef struct _keytype {
char ch, chShift;
} Key;
//!On-screen keyboard
class GuiKeyboard : public GuiWindow
{
public:
GuiKeyboard(char * t, u32 m);
~GuiKeyboard();
void Update(GuiTrigger * t);
char kbtextstr[256];
protected:
u32 kbtextmaxlen;
Key keys[4][11];
int shift;
int caps;
GuiText * kbText;
GuiImage * keyTextboxImg;
GuiText * keyCapsText;
GuiImage * keyCapsImg;
GuiImage * keyCapsOverImg;
GuiButton * keyCaps;
GuiText * keyShiftText;
GuiImage * keyShiftImg;
GuiImage * keyShiftOverImg;
GuiButton * keyShift;
GuiText * keyBackText;
GuiImage * keyBackImg;
GuiImage * keyBackOverImg;
GuiButton * keyBack;
GuiImage * keySpaceImg;
GuiImage * keySpaceOverImg;
GuiButton * keySpace;
GuiButton * keyBtn[4][11];
GuiImage * keyImg[4][11];
GuiImage * keyImgOver[4][11];
GuiText * keyTxt[4][11];
GuiImageData * keyTextbox;
GuiImageData * key;
GuiImageData * keyOver;
GuiImageData * keyMedium;
GuiImageData * keyMediumOver;
GuiImageData * keyLarge;
GuiImageData * keyLargeOver;
GuiSound * keySoundOver;
GuiSound * keySoundClick;
GuiTrigger * trigA;
}; };
#endif #endif

View File

@ -1,231 +0,0 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Tantric February 2009
*
* gui_button.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
/**
* Constructor for the GuiButton class.
*/
GuiButton::GuiButton(int w, int h)
{
width = w;
height = h;
image = NULL;
imageOver = NULL;
icon = NULL;
iconOver = NULL;
for(int i=0; i < 3; i++)
{
label[i] = NULL;
labelOver[i] = NULL;
}
soundOver = NULL;
soundClick = NULL;
selectable = true;
clickable = true;
}
/**
* Destructor for the GuiButton class.
*/
GuiButton::~GuiButton()
{
}
void GuiButton::SetImage(GuiImage* img)
{
image = img;
if(img)
img->SetParent(this);
}
void GuiButton::SetImageOver(GuiImage* img)
{
imageOver = img;
if(img)
img->SetParent(this);
}
void GuiButton::SetIcon(GuiImage* img)
{
icon = img;
if(img)
img->SetParent(this);
}
void GuiButton::SetIconOver(GuiImage* img)
{
iconOver = img;
if(img)
img->SetParent(this);
}
void GuiButton::SetLabel(GuiText* txt)
{
label[0] = txt;
if(txt)
txt->SetParent(this);
}
void GuiButton::SetLabelOver(GuiText* txt)
{
labelOver[0] = txt;
if(txt)
txt->SetParent(this);
}
void GuiButton::SetLabel(GuiText* txt, int n)
{
label[n] = txt;
if(txt)
txt->SetParent(this);
}
void GuiButton::SetLabelOver(GuiText* txt, int n)
{
labelOver[n] = txt;
if(txt)
txt->SetParent(this);
}
void GuiButton::SetSoundOver(GuiSound * snd)
{
soundOver = snd;
}
void GuiButton::SetSoundClick(GuiSound * snd)
{
soundClick = snd;
}
/**
* Draw the button on screen
*/
void GuiButton::Draw()
{
if(!this->IsVisible())
return;
// draw image
if(state == STATE_SELECTED && imageOver)
imageOver->Draw();
else if(image)
image->Draw();
// draw icon
if(state == STATE_SELECTED && iconOver)
iconOver->Draw();
else if(icon)
icon->Draw();
// draw text
for(int i=0; i<3; i++)
{
if(state == STATE_SELECTED && labelOver[i])
labelOver[i]->Draw();
else if(label[i])
label[i]->Draw();
}
this->UpdateEffects();
}
void GuiButton::Update(GuiTrigger * t)
{
if(state == STATE_CLICKED || state == STATE_DISABLED || !t)
return;
else if(parentElement && parentElement->GetState() == STATE_DISABLED)
return;
#ifdef HW_RVL
// cursor
if(t->wpad.ir.valid)
{
if(this->IsInside(t->wpad.ir.x, t->wpad.ir.y))
{
if(state == STATE_DEFAULT) // we weren't on the button before!
{
state = STATE_SELECTED;
if(this->Rumble())
rumbleRequest[t->chan] = 1;
if(soundOver)
soundOver->Play();
if(effectsOver && !effects)
{
// initiate effects
effects = effectsOver;
effectAmount = effectAmountOver;
effectTarget = effectTargetOver;
}
}
}
else
{
if(state == STATE_SELECTED)
state = STATE_DEFAULT;
if(effectTarget == effectTargetOver && effectAmount == effectAmountOver)
{
// initiate effects (in reverse)
effects = effectsOver;
effectAmount = -effectAmountOver;
effectTarget = 100;
}
}
}
#endif
// button triggers
if(this->IsClickable())
{
for(int i=0; i<2; i++)
{
if(trigger[i] && (trigger[i]->chan == -1 || trigger[i]->chan == t->chan))
{
// higher 16 bits only (wiimote)
s32 wm_btns = t->wpad.btns_d << 16;
s32 wm_btns_trig = trigger[i]->wpad.btns_d << 16;
// lower 16 bits only (classic controller)
s32 cc_btns = t->wpad.btns_d >> 16;
s32 cc_btns_trig = trigger[i]->wpad.btns_d >> 16;
if(
(t->wpad.btns_d > 0 &&
wm_btns == wm_btns_trig ||
(cc_btns == cc_btns_trig && t->wpad.exp.type == EXP_CLASSIC)) ||
(t->pad.btns_d == trigger[i]->pad.btns_d && t->pad.btns_d > 0))
{
if(state == STATE_SELECTED)
{
state = STATE_CLICKED;
if(soundClick)
soundClick->Play();
}
else if(trigger[i]->type == TRIGGER_BUTTON_ONLY)
{
state = STATE_CLICKED;
}
else if(trigger[i]->type == TRIGGER_BUTTON_ONLY_IN_FOCUS &&
parentElement->IsFocused())
{
state = STATE_CLICKED;
}
}
}
}
}
if(updateCB)
updateCB(this);
}

View File

@ -25,7 +25,6 @@ GuiElement::GuiElement()
trigger[0] = NULL; trigger[0] = NULL;
trigger[1] = NULL; trigger[1] = NULL;
parentElement = NULL; parentElement = NULL;
rumble = true;
selectable = false; selectable = false;
clickable = false; clickable = false;
visible = true; visible = true;
@ -284,16 +283,6 @@ void GuiElement::SetTrigger(u8 i, GuiTrigger * t)
trigger[i] = t; trigger[i] = t;
} }
bool GuiElement::Rumble()
{
return rumble;
}
void GuiElement::SetRumble(bool r)
{
rumble = r;
}
int GuiElement::GetEffect() int GuiElement::GetEffect()
{ {
return effects; return effects;

View File

@ -1,328 +0,0 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Tantric February 2009
*
* gui_filebrowser.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
#include "filebrowser.h"
/**
* Constructor for the GuiFileBrowser class.
*/
GuiFileBrowser::GuiFileBrowser(int w, int h)
{
width = w;
height = h;
selectedItem = 0;
selectable = true;
listChanged = true; // trigger an initial list update
focus = 0; // allow focus
trigA = new GuiTrigger;
if(GCSettings.WiimoteOrientation)
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
else
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
btnSoundOver = new GuiSound(button_over_pcm, button_over_pcm_size, SOUND_PCM);
btnSoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, SOUND_PCM);
bgGameSelection = new GuiImageData(bg_game_selection_png);
bgGameSelectionImg = new GuiImage(bgGameSelection);
bgGameSelectionImg->SetParent(this);
bgGameSelectionImg->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
bgGameSelectionEntry = new GuiImageData(bg_game_selection_entry_png);
gameFolder = new GuiImageData(folder_png);
scrollbar = new GuiImageData(scrollbar_png);
scrollbarImg = new GuiImage(scrollbar);
scrollbarImg->SetParent(this);
scrollbarImg->SetAlignment(ALIGN_RIGHT, ALIGN_TOP);
scrollbarImg->SetPosition(0, 30);
arrowDown = new GuiImageData(scrollbar_arrowdown_png);
arrowDownImg = new GuiImage(arrowDown);
arrowDownOver = new GuiImageData(scrollbar_arrowdown_over_png);
arrowDownOverImg = new GuiImage(arrowDownOver);
arrowUp = new GuiImageData(scrollbar_arrowup_png);
arrowUpImg = new GuiImage(arrowUp);
arrowUpOver = new GuiImageData(scrollbar_arrowup_over_png);
arrowUpOverImg = new GuiImage(arrowUpOver);
scrollbarBox = new GuiImageData(scrollbar_box_png);
scrollbarBoxImg = new GuiImage(scrollbarBox);
scrollbarBoxOver = new GuiImageData(scrollbar_box_over_png);
scrollbarBoxOverImg = new GuiImage(scrollbarBoxOver);
arrowUpBtn = new GuiButton(arrowUpImg->GetWidth(), arrowUpImg->GetHeight());
arrowUpBtn->SetParent(this);
arrowUpBtn->SetImage(arrowUpImg);
arrowUpBtn->SetImageOver(arrowUpOverImg);
arrowUpBtn->SetAlignment(ALIGN_RIGHT, ALIGN_TOP);
arrowUpBtn->SetSelectable(false);
arrowUpBtn->SetTrigger(trigA);
arrowUpBtn->SetSoundOver(btnSoundOver);
arrowUpBtn->SetSoundClick(btnSoundClick);
arrowDownBtn = new GuiButton(arrowDownImg->GetWidth(), arrowDownImg->GetHeight());
arrowDownBtn->SetParent(this);
arrowDownBtn->SetImage(arrowDownImg);
arrowDownBtn->SetImageOver(arrowDownOverImg);
arrowDownBtn->SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM);
arrowDownBtn->SetSelectable(false);
arrowDownBtn->SetTrigger(trigA);
arrowDownBtn->SetSoundOver(btnSoundOver);
arrowDownBtn->SetSoundClick(btnSoundClick);
scrollbarBoxBtn = new GuiButton(scrollbarBoxImg->GetWidth(), scrollbarBoxImg->GetHeight());
scrollbarBoxBtn->SetParent(this);
scrollbarBoxBtn->SetImage(scrollbarBoxImg);
scrollbarBoxBtn->SetImageOver(scrollbarBoxOverImg);
scrollbarBoxBtn->SetAlignment(ALIGN_RIGHT, ALIGN_TOP);
scrollbarBoxBtn->SetSelectable(false);
for(int i=0; i<PAGESIZE; i++)
{
gameListText[i] = new GuiText("Game",22, (GXColor){0, 0, 0, 0xff});
gameListText[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
gameListText[i]->SetPosition(5,0);
gameListBg[i] = new GuiImage(bgGameSelectionEntry);
gameListFolder[i] = new GuiImage(gameFolder);
gameList[i] = new GuiButton(380, 30);
gameList[i]->SetParent(this);
gameList[i]->SetLabel(gameListText[i]);
gameList[i]->SetImageOver(gameListBg[i]);
gameList[i]->SetPosition(2,30*i+3);
gameList[i]->SetTrigger(trigA);
gameList[i]->SetSoundClick(btnSoundClick);
}
}
/**
* Destructor for the GuiFileBrowser class.
*/
GuiFileBrowser::~GuiFileBrowser()
{
delete arrowUpBtn;
delete arrowDownBtn;
delete scrollbarBoxBtn;
delete bgGameSelectionImg;
delete scrollbarImg;
delete arrowDownImg;
delete arrowDownOverImg;
delete arrowUpImg;
delete arrowUpOverImg;
delete scrollbarBoxImg;
delete scrollbarBoxOverImg;
delete bgGameSelection;
delete bgGameSelectionEntry;
delete gameFolder;
delete scrollbar;
delete arrowDown;
delete arrowDownOver;
delete arrowUp;
delete arrowUpOver;
delete scrollbarBox;
delete scrollbarBoxOver;
delete btnSoundOver;
delete btnSoundClick;
delete trigA;
for(int i=0; i<PAGESIZE; i++)
{
delete gameListText[i];
delete gameList[i];
delete gameListBg[i];
delete gameListFolder[i];
}
}
void GuiFileBrowser::SetFocus(int f)
{
focus = f;
for(int i=0; i<PAGESIZE; i++)
gameList[i]->ResetState();
if(f == 1)
gameList[selectedItem]->SetState(STATE_SELECTED);
}
void GuiFileBrowser::ResetState()
{
state = STATE_DEFAULT;
selectedItem = 0;
for(int i=0; i<PAGESIZE; i++)
{
gameList[i]->ResetState();
}
}
void GuiFileBrowser::TriggerUpdate()
{
listChanged = true;
}
/**
* Draw the button on screen
*/
void GuiFileBrowser::Draw()
{
if(!this->IsVisible())
return;
bgGameSelectionImg->Draw();
for(int i=0; i<PAGESIZE; i++)
{
gameList[i]->Draw();
}
scrollbarImg->Draw();
arrowUpBtn->Draw();
arrowDownBtn->Draw();
scrollbarBoxBtn->Draw();
this->UpdateEffects();
}
void GuiFileBrowser::Update(GuiTrigger * t)
{
if(state == STATE_DISABLED || !t)
return;
// update the location of the scroll box based on the position in the file list
int position = 136*(browser.pageIndex + selectedItem) / browser.numEntries;
scrollbarBoxBtn->SetPosition(0,position+36);
arrowUpBtn->Update(t);
arrowDownBtn->Update(t);
scrollbarBoxBtn->Update(t);
// pad/joystick navigation
if(!focus)
{
goto endNavigation; // skip navigation
listChanged = false;
}
if(t->Right() || arrowDownBtn->GetState() == STATE_CLICKED)
{
if(browser.pageIndex < browser.numEntries && browser.numEntries > PAGESIZE)
{
browser.pageIndex += PAGESIZE;
if(browser.pageIndex+PAGESIZE >= browser.numEntries)
browser.pageIndex = browser.numEntries-PAGESIZE;
listChanged = true;
}
arrowDownBtn->ResetState();
}
else if(t->Left() || arrowUpBtn->GetState() == STATE_CLICKED)
{
if(browser.pageIndex > 0)
{
browser.pageIndex -= PAGESIZE;
if(browser.pageIndex < 0)
browser.pageIndex = 0;
listChanged = true;
}
arrowUpBtn->ResetState();
}
else if(t->Down())
{
if(browser.pageIndex + selectedItem + 1 < browser.numEntries)
{
if(selectedItem == PAGESIZE-1)
{
// move list down by 1
browser.pageIndex++;
listChanged = true;
}
else if(gameList[selectedItem+1]->IsVisible())
{
gameList[selectedItem]->ResetState();
gameList[++selectedItem]->SetState(STATE_SELECTED);
}
}
}
else if(t->Up())
{
if(selectedItem == 0 && browser.pageIndex + selectedItem > 0)
{
// move list up by 1
browser.pageIndex--;
listChanged = true;
}
else if(selectedItem > 0)
{
gameList[selectedItem]->ResetState();
gameList[--selectedItem]->SetState(STATE_SELECTED);
}
}
endNavigation:
for(int i=0; i<PAGESIZE; i++)
{
if(listChanged)
{
if(browser.pageIndex+i < browser.numEntries)
{
if(gameList[i]->GetState() == STATE_DISABLED)
gameList[i]->SetState(STATE_DEFAULT);
gameList[i]->SetVisible(true);
gameListText[i]->SetText(browserList[browser.pageIndex+i].displayname);
if(browserList[browser.pageIndex+i].isdir) // directory
{
gameList[i]->SetIcon(gameListFolder[i]);
gameListText[i]->SetPosition(30,0);
}
else
{
gameList[i]->SetIcon(NULL);
gameListText[i]->SetPosition(10,0);
}
}
else
{
gameList[i]->SetVisible(false);
gameList[i]->SetState(STATE_DISABLED);
}
}
if(focus)
{
if(i != selectedItem && gameList[i]->GetState() == STATE_SELECTED)
gameList[i]->ResetState();
else if(i == selectedItem && gameList[i]->GetState() == STATE_DEFAULT)
gameList[selectedItem]->SetState(STATE_SELECTED);
}
gameList[i]->Update(t);
if(gameList[i]->GetState() == STATE_SELECTED)
{
selectedItem = i;
browser.selIndex = browser.pageIndex + i;
}
}
listChanged = false;
if(updateCB)
updateCB(this);
}

View File

@ -1,220 +0,0 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Tantric February 2009
*
* gui_image.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
/**
* Constructor for the GuiImage class.
*/
GuiImage::GuiImage(GuiImageData * img)
{
image = img->GetImage();
width = img->GetWidth();
height = img->GetHeight();
imageangle = 0;
tile = -1;
stripe = 0;
imgType = IMAGE_DATA;
}
GuiImage::GuiImage(u8 * img, int w, int h)
{
image = img;
width = w;
height = h;
imageangle = 0;
tile = -1;
stripe = 0;
imgType = IMAGE_TEXTURE;
}
GuiImage::GuiImage(int w, int h, GXColor c)
{
image = (u8 *)memalign (32, w * h * 4);
width = w;
height = h;
imageangle = 0;
tile = -1;
stripe = 0;
imgType = IMAGE_COLOR;
if(!image)
return;
int x, y;
for(y=0; y < h; y++)
{
for(x=0; x < w; x++)
{
this->SetPixel(x, y, c);
}
}
int len = w*h*4;
if(len%32) len += (32-len%32);
DCFlushRange(image, len);
}
/**
* Destructor for the GuiImage class.
*/
GuiImage::~GuiImage()
{
if(imgType == IMAGE_COLOR && image)
free(image);
}
u8 * GuiImage::GetImage()
{
return image;
}
void GuiImage::SetImage(GuiImageData * img)
{
image = img->GetImage();
width = img->GetWidth();
height = img->GetHeight();
imgType = IMAGE_DATA;
}
void GuiImage::SetImage(u8 * img, int w, int h)
{
image = img;
width = w;
height = h;
imgType = IMAGE_TEXTURE;
}
void GuiImage::SetAngle(float a)
{
imageangle = a;
}
void GuiImage::SetTile(int t)
{
tile = t;
}
GXColor GuiImage::GetPixel(int x, int y)
{
if(!image || this->GetWidth() <= 0 || x < 0 || y < 0)
return (GXColor){0, 0, 0, 0};
u32 offset = (((y >> 2)<<4)*this->GetWidth()) + ((x >> 2)<<6) + (((y%4 << 2) + x%4 ) << 1);
GXColor color;
color.a = *(image+offset);
color.r = *(image+offset+1);
color.g = *(image+offset+32);
color.b = *(image+offset+33);
return color;
}
void GuiImage::SetPixel(int x, int y, GXColor color)
{
if(!image || this->GetWidth() <= 0 || x < 0 || y < 0)
return;
u32 offset = (((y >> 2)<<4)*this->GetWidth()) + ((x >> 2)<<6) + (((y%4 << 2) + x%4 ) << 1);
*(image+offset) = color.a;
*(image+offset+1) = color.r;
*(image+offset+32) = color.g;
*(image+offset+33) = color.b;
}
void GuiImage::SetStripe(int s)
{
stripe = s;
}
void GuiImage::ColorStripe(int shift)
{
int x, y;
GXColor color;
int alt = 0;
for(y=0; y < this->GetHeight(); y++)
{
if(y % 3 == 0)
alt ^= 1;
for(x=0; x < this->GetWidth(); x++)
{
color = GetPixel(x, y);
if(alt)
{
if(color.r < 255-shift)
color.r += shift;
else
color.r = 255;
if(color.g < 255-shift)
color.g += shift;
else
color.g = 255;
if(color.b < 255-shift)
color.b += shift;
else
color.b = 255;
color.a = 255;
}
else
{
if(color.r > shift)
color.r -= shift;
else
color.r = 0;
if(color.g > shift)
color.g -= shift;
else
color.g = 0;
if(color.b > shift)
color.b -= shift;
else
color.b = 0;
color.a = 255;
}
SetPixel(x, y, color);
}
}
}
/**
* Draw the button on screen
*/
void GuiImage::Draw()
{
if(!image || !this->IsVisible() || tile == 0)
return;
float currScale = this->GetScale();
int currLeft = this->GetLeft();
if(tile > 0)
{
for(int i=0; i<tile; i++)
Menu_DrawImg(currLeft+width*i, this->GetTop(), width, height, image, imageangle, currScale, currScale, this->GetAlpha());
}
else
{
// temporary (maybe), used to correct offset for scaled images
if(scale != 1)
currLeft = currLeft - width/2 + (width*scale)/2;
Menu_DrawImg(currLeft, this->GetTop(), width, height, image, imageangle, currScale, currScale, this->GetAlpha());
}
if(stripe > 0)
for(int y=0; y < this->GetHeight(); y+=6)
Menu_DrawRectangle(currLeft,this->GetTop()+y,this->GetWidth(),3,(GXColor){0, 0, 0, stripe},1);
this->UpdateEffects();
}

View File

@ -15,44 +15,25 @@
*/ */
GuiImageData::GuiImageData(const u8 * img) GuiImageData::GuiImageData(const u8 * img)
{ {
data = NULL; if(img == NULL)
width = 0; {
height = 0; data = NULL;
width = 0;
if(img) height = 0;
}
else
{ {
PNGUPROP imgProp; PNGUPROP imgProp;
IMGCTX ctx = PNGU_SelectImageFromBuffer(img); IMGCTX ctx;
if(!ctx) ctx = PNGU_SelectImageFromBuffer(img);
return; PNGU_GetImageProperties (ctx, &imgProp);
width = imgProp.imgWidth;
int res = PNGU_GetImageProperties(ctx, &imgProp); height = imgProp.imgHeight;
data = (u8 *)memalign (32, imgProp.imgWidth * imgProp.imgHeight * 4);
if(res == PNGU_OK) PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, data, 255);
{
int len = imgProp.imgWidth * imgProp.imgHeight * 4;
if(len%32) len += (32-len%32);
data = (u8 *)memalign (32, len);
if(data)
{
res = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, data, 255);
if(res == PNGU_OK)
{
width = imgProp.imgWidth;
height = imgProp.imgHeight;
DCFlushRange(data, len);
}
else
{
free(data);
data = NULL;
}
}
}
PNGU_ReleaseImageContext (ctx); PNGU_ReleaseImageContext (ctx);
DCFlushRange (data, imgProp.imgWidth * imgProp.imgHeight * 4);
} }
} }

View File

@ -1,330 +0,0 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Tantric February 2009
*
* gui_keyboard.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
/**
* Constructor for the GuiKeyboard class.
*/
GuiKeyboard::GuiKeyboard(char * t, u32 max)
{
width = 540;
height = 400;
shift = 0;
caps = 0;
selectable = true;
focus = 0; // allow focus
alignmentHor = ALIGN_CENTRE;
alignmentVert = ALIGN_MIDDLE;
strncpy(kbtextstr, t, max);
kbtextstr[max] = 0;
kbtextmaxlen = max;
Key thekeys[4][11] = {
{
{'1','!'},
{'2','@'},
{'3','#'},
{'4','$'},
{'5','%'},
{'6','^'},
{'7','&'},
{'8','*'},
{'9','('},
{'0',')'},
{'\0','\0'}
},
{
{'q','Q'},
{'w','W'},
{'e','E'},
{'r','R'},
{'t','T'},
{'y','Y'},
{'u','U'},
{'i','I'},
{'o','O'},
{'p','P'},
{'-','_'}
},
{
{'a','A'},
{'s','S'},
{'d','D'},
{'f','F'},
{'g','G'},
{'h','H'},
{'j','J'},
{'k','K'},
{'l','L'},
{':',';'},
{'\'','"'}
},
{
{'z','Z'},
{'x','X'},
{'c','C'},
{'v','V'},
{'b','B'},
{'n','N'},
{'m','M'},
{',','<'},
{'.','>'},
{'/','?'},
{'\0','\0'}
}
};
memcpy(keys, thekeys, sizeof(thekeys));
keyTextbox = new GuiImageData(keyboard_textbox_png);
keyTextboxImg = new GuiImage(keyTextbox);
keyTextboxImg->SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
keyTextboxImg->SetPosition(0, 0);
this->Append(keyTextboxImg);
kbText = new GuiText(kbtextstr, 22, (GXColor){0, 0, 0, 0xff});
kbText->SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
kbText->SetPosition(0, 13);
this->Append(kbText);
key = new GuiImageData(keyboard_key_png);
keyOver = new GuiImageData(keyboard_key_over_png);
keyMedium = new GuiImageData(keyboard_mediumkey_png);
keyMediumOver = new GuiImageData(keyboard_mediumkey_over_png);
keyLarge = new GuiImageData(keyboard_largekey_png);
keyLargeOver = new GuiImageData(keyboard_largekey_over_png);
keySoundOver = new GuiSound(button_over_pcm, button_over_pcm_size, SOUND_PCM);
keySoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, SOUND_PCM);
trigA = new GuiTrigger;
if(GCSettings.WiimoteOrientation)
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
else
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
keyBackImg = new GuiImage(keyMedium);
keyBackOverImg = new GuiImage(keyMediumOver);
keyBackText = new GuiText("Back", 22, (GXColor){0, 0, 0, 0xff});
keyBack = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight());
keyBack->SetImage(keyBackImg);
keyBack->SetImageOver(keyBackOverImg);
keyBack->SetLabel(keyBackText);
keyBack->SetSoundOver(keySoundOver);
keyBack->SetSoundClick(keySoundClick);
keyBack->SetTrigger(trigA);
keyBack->SetPosition(10*42+40, 0*42+80);
keyBack->SetEffectGrow();
this->Append(keyBack);
keyCapsImg = new GuiImage(keyMedium);
keyCapsOverImg = new GuiImage(keyMediumOver);
keyCapsText = new GuiText("Caps", 22, (GXColor){0, 0, 0, 0xff});
keyCaps = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight());
keyCaps->SetImage(keyCapsImg);
keyCaps->SetImageOver(keyCapsOverImg);
keyCaps->SetLabel(keyCapsText);
keyCaps->SetSoundOver(keySoundOver);
keyCaps->SetSoundClick(keySoundClick);
keyCaps->SetTrigger(trigA);
keyCaps->SetPosition(0, 2*42+80);
keyCaps->SetEffectGrow();
this->Append(keyCaps);
keyShiftImg = new GuiImage(keyMedium);
keyShiftOverImg = new GuiImage(keyMediumOver);
keyShiftText = new GuiText("Shift", 22, (GXColor){0, 0, 0, 0xff});
keyShift = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight());
keyShift->SetImage(keyShiftImg);
keyShift->SetImageOver(keyShiftOverImg);
keyShift->SetLabel(keyShiftText);
keyShift->SetSoundOver(keySoundOver);
keyShift->SetSoundClick(keySoundClick);
keyShift->SetTrigger(trigA);
keyShift->SetPosition(21, 3*42+80);
keyShift->SetEffectGrow();
this->Append(keyShift);
keySpaceImg = new GuiImage(keyLarge);
keySpaceOverImg = new GuiImage(keyLargeOver);
keySpace = new GuiButton(keyLarge->GetWidth(), keyLarge->GetHeight());
keySpace->SetImage(keySpaceImg);
keySpace->SetImageOver(keySpaceOverImg);
keySpace->SetSoundOver(keySoundOver);
keySpace->SetSoundClick(keySoundClick);
keySpace->SetTrigger(trigA);
keySpace->SetPosition(0, 4*42+80);
keySpace->SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
keySpace->SetEffectGrow();
this->Append(keySpace);
for(int i=0; i<4; i++)
{
for(int j=0; j<11; j++)
{
if(keys[i][j].ch != '\0')
{
keyImg[i][j] = new GuiImage(key);
keyImgOver[i][j] = new GuiImage(keyOver);
keyTxt[i][j] = new GuiText(NULL, 22, (GXColor){0, 0, 0, 0xff});
keyTxt[i][j]->SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM);
keyTxt[i][j]->SetPosition(0, -10);
keyBtn[i][j] = new GuiButton(key->GetWidth(), key->GetHeight());
keyBtn[i][j]->SetImage(keyImg[i][j]);
keyBtn[i][j]->SetImageOver(keyImgOver[i][j]);
keyBtn[i][j]->SetSoundOver(keySoundOver);
keyBtn[i][j]->SetSoundClick(keySoundClick);
keyBtn[i][j]->SetTrigger(trigA);
keyBtn[i][j]->SetLabel(keyTxt[i][j]);
keyBtn[i][j]->SetPosition(j*42+21*i+40, i*42+80);
keyBtn[i][j]->SetEffectGrow();
this->Append(keyBtn[i][j]);
}
}
}
}
/**
* Destructor for the GuiKeyboard class.
*/
GuiKeyboard::~GuiKeyboard()
{
delete kbText;
delete keyTextbox;
delete keyTextboxImg;
delete keyCapsText;
delete keyCapsImg;
delete keyCapsOverImg;
delete keyCaps;
delete keyShiftText;
delete keyShiftImg;
delete keyShiftOverImg;
delete keyShift;
delete keyBackText;
delete keyBackImg;
delete keyBackOverImg;
delete keyBack;
delete keySpaceImg;
delete keySpaceOverImg;
delete keySpace;
delete key;
delete keyOver;
delete keyMedium;
delete keyMediumOver;
delete keyLarge;
delete keyLargeOver;
delete keySoundOver;
delete keySoundClick;
delete trigA;
for(int i=0; i<4; i++)
{
for(int j=0; j<11; j++)
{
if(keys[i][j].ch != '\0')
{
delete keyImg[i][j];
delete keyImgOver[i][j];
delete keyTxt[i][j];
delete keyBtn[i][j];
}
}
}
}
void GuiKeyboard::Update(GuiTrigger * t)
{
if(_elements.size() == 0 || (state == STATE_DISABLED && parentElement))
return;
for (u8 i = 0; i < _elements.size(); i++)
{
try { _elements.at(i)->Update(t); }
catch (exception& e) { }
}
if(keySpace->GetState() == STATE_CLICKED)
{
if(strlen(kbtextstr) < kbtextmaxlen)
{
kbtextstr[strlen(kbtextstr)] = ' ';
kbText->SetText(kbtextstr);
}
keySpace->SetState(STATE_SELECTED);
}
else if(keyBack->GetState() == STATE_CLICKED)
{
kbtextstr[strlen(kbtextstr)-1] = 0;
kbText->SetText(kbtextstr);
keyBack->SetState(STATE_SELECTED);
}
else if(keyShift->GetState() == STATE_CLICKED)
{
shift ^= 1;
keyShift->SetState(STATE_SELECTED);
}
else if(keyCaps->GetState() == STATE_CLICKED)
{
caps ^= 1;
keyCaps->SetState(STATE_SELECTED);
}
char txt[2] = { 0, 0 };
for(int i=0; i<4; i++)
{
for(int j=0; j<11; j++)
{
if(keys[i][j].ch != '\0')
{
if(shift || caps)
txt[0] = keys[i][j].chShift;
else
txt[0] = keys[i][j].ch;
keyTxt[i][j]->SetText(txt);
if(keyBtn[i][j]->GetState() == STATE_CLICKED)
{
if(strlen(kbtextstr) < kbtextmaxlen)
{
if(shift || caps)
{
kbtextstr[strlen(kbtextstr)] = keys[i][j].chShift;
if(shift) shift ^= 1;
}
else
{
kbtextstr[strlen(kbtextstr)] = keys[i][j].ch;
}
}
kbText->SetText(kbtextstr);
keyBtn[i][j]->SetState(STATE_SELECTED);
}
}
}
}
this->ToggleFocus(t);
if(focus) // only send actions to this window if it's in focus
{
// pad/joystick navigation
if(t->Right())
this->MoveSelectionHor(1);
else if(t->Left())
this->MoveSelectionHor(-1);
else if(t->Down())
this->MoveSelectionVert(1);
else if(t->Up())
this->MoveSelectionVert(-1);
}
}

View File

@ -1,351 +0,0 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Tantric February 2009
*
* gui_optionbrowser.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
#include "filebrowser.h"
/**
* Constructor for the GuiOptionBrowser class.
*/
GuiOptionBrowser::GuiOptionBrowser(int w, int h, OptionList * l)
{
width = w;
height = h;
options = l;
selectable = true;
listOffset = this->FindMenuItem(-1, 1);
selectedItem = 0;
focus = 0; // allow focus
trigA = new GuiTrigger;
if(GCSettings.WiimoteOrientation)
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
else
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
btnSoundOver = new GuiSound(button_over_pcm, button_over_pcm_size, SOUND_PCM);
btnSoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, SOUND_PCM);
bgOptions = new GuiImageData(bg_options_png);
bgOptionsImg = new GuiImage(bgOptions);
bgOptionsImg->SetParent(this);
bgOptionsImg->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
bgOptionsEntry = new GuiImageData(bg_options_entry_png);
scrollbar = new GuiImageData(scrollbar_png);
scrollbarImg = new GuiImage(scrollbar);
scrollbarImg->SetParent(this);
scrollbarImg->SetAlignment(ALIGN_RIGHT, ALIGN_TOP);
scrollbarImg->SetPosition(0, 30);
arrowDown = new GuiImageData(scrollbar_arrowdown_png);
arrowDownImg = new GuiImage(arrowDown);
arrowDownOver = new GuiImageData(scrollbar_arrowdown_over_png);
arrowDownOverImg = new GuiImage(arrowDownOver);
arrowUp = new GuiImageData(scrollbar_arrowup_png);
arrowUpImg = new GuiImage(arrowUp);
arrowUpOver = new GuiImageData(scrollbar_arrowup_over_png);
arrowUpOverImg = new GuiImage(arrowUpOver);
scrollbarBox = new GuiImageData(scrollbar_box_png);
scrollbarBoxImg = new GuiImage(scrollbarBox);
scrollbarBoxOver = new GuiImageData(scrollbar_box_over_png);
scrollbarBoxOverImg = new GuiImage(scrollbarBoxOver);
arrowUpBtn = new GuiButton(arrowUpImg->GetWidth(), arrowUpImg->GetHeight());
arrowUpBtn->SetParent(this);
arrowUpBtn->SetImage(arrowUpImg);
arrowUpBtn->SetImageOver(arrowUpOverImg);
arrowUpBtn->SetAlignment(ALIGN_RIGHT, ALIGN_TOP);
arrowUpBtn->SetSelectable(false);
arrowUpBtn->SetTrigger(trigA);
arrowUpBtn->SetSoundOver(btnSoundOver);
arrowUpBtn->SetSoundClick(btnSoundClick);
arrowDownBtn = new GuiButton(arrowDownImg->GetWidth(), arrowDownImg->GetHeight());
arrowDownBtn->SetParent(this);
arrowDownBtn->SetImage(arrowDownImg);
arrowDownBtn->SetImageOver(arrowDownOverImg);
arrowDownBtn->SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM);
arrowDownBtn->SetSelectable(false);
arrowDownBtn->SetTrigger(trigA);
arrowDownBtn->SetSoundOver(btnSoundOver);
arrowDownBtn->SetSoundClick(btnSoundClick);
scrollbarBoxBtn = new GuiButton(scrollbarBoxImg->GetWidth(), scrollbarBoxImg->GetHeight());
scrollbarBoxBtn->SetParent(this);
scrollbarBoxBtn->SetImage(scrollbarBoxImg);
scrollbarBoxBtn->SetImageOver(scrollbarBoxOverImg);
scrollbarBoxBtn->SetAlignment(ALIGN_RIGHT, ALIGN_TOP);
scrollbarBoxBtn->SetSelectable(false);
for(int i=0; i<PAGESIZE; i++)
{
optionTxt[i] = new GuiText(options->name[i], 22, (GXColor){0, 0, 0, 0xff});
optionTxt[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
optionTxt[i]->SetPosition(8,0);
optionVal[i] = new GuiText(NULL, 22, (GXColor){0, 0, 0, 0xff});
optionVal[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
optionVal[i]->SetPosition(250,0);
optionBg[i] = new GuiImage(bgOptionsEntry);
optionBtn[i] = new GuiButton(512,30);
optionBtn[i]->SetParent(this);
optionBtn[i]->SetLabel(optionTxt[i], 0);
optionBtn[i]->SetLabel(optionVal[i], 1);
optionBtn[i]->SetImageOver(optionBg[i]);
optionBtn[i]->SetPosition(0,30*i+3);
optionBtn[i]->SetTrigger(trigA);
optionBtn[i]->SetSoundClick(btnSoundClick);
}
}
/**
* Destructor for the GuiOptionBrowser class.
*/
GuiOptionBrowser::~GuiOptionBrowser()
{
delete arrowUpBtn;
delete arrowDownBtn;
delete scrollbarBoxBtn;
delete bgOptionsImg;
delete scrollbarImg;
delete arrowDownImg;
delete arrowDownOverImg;
delete arrowUpImg;
delete arrowUpOverImg;
delete scrollbarBoxImg;
delete scrollbarBoxOverImg;
delete bgOptions;
delete bgOptionsEntry;
delete scrollbar;
delete arrowDown;
delete arrowDownOver;
delete arrowUp;
delete arrowUpOver;
delete scrollbarBox;
delete scrollbarBoxOver;
delete trigA;
delete btnSoundOver;
delete btnSoundClick;
for(int i=0; i<PAGESIZE; i++)
{
delete optionTxt[i];
delete optionVal[i];
delete optionBg[i];
delete optionBtn[i];
}
}
void GuiOptionBrowser::SetCol2Position(int x)
{
for(int i=0; i<PAGESIZE; i++)
optionVal[i]->SetPosition(x,0);
}
void GuiOptionBrowser::SetFocus(int f)
{
focus = f;
for(int i=0; i<PAGESIZE; i++)
optionBtn[i]->ResetState();
if(f == 1)
optionBtn[selectedItem]->SetState(STATE_SELECTED);
}
void GuiOptionBrowser::ResetState()
{
if(state != STATE_DISABLED)
state = STATE_DEFAULT;
for(int i=0; i<PAGESIZE; i++)
{
optionBtn[i]->ResetState();
}
}
int GuiOptionBrowser::GetClickedOption()
{
int found = -1;
for(int i=0; i<PAGESIZE; i++)
{
if(optionBtn[i]->GetState() == STATE_CLICKED)
{
optionBtn[i]->SetState(STATE_SELECTED);
found = optionIndex[i];
break;
}
}
return found;
}
/****************************************************************************
* FindMenuItem
*
* Help function to find the next visible menu item on the list
***************************************************************************/
int GuiOptionBrowser::FindMenuItem(int currentItem, int direction)
{
int nextItem = currentItem + direction;
if(nextItem < 0 || nextItem >= options->length)
return -1;
if(strlen(options->name[nextItem]) > 0)
return nextItem;
else
return FindMenuItem(nextItem, direction);
}
/**
* Draw the button on screen
*/
void GuiOptionBrowser::Draw()
{
if(!this->IsVisible())
return;
bgOptionsImg->Draw();
int next = listOffset;
for(int i=0; i<PAGESIZE; i++)
{
if(next >= 0)
{
optionBtn[i]->Draw();
next = this->FindMenuItem(next, 1);
}
else
break;
}
scrollbarImg->Draw();
arrowUpBtn->Draw();
arrowDownBtn->Draw();
scrollbarBoxBtn->Draw();
this->UpdateEffects();
}
void GuiOptionBrowser::Update(GuiTrigger * t)
{
if(state == STATE_DISABLED || !t)
return;
int next, prev;
// update the location of the scroll box based on the position in the option list
int position = 136*(listOffset+selectedItem)/options->length;
if(position > 130)
position = 136;
scrollbarBoxBtn->SetPosition(0,position+36);
arrowUpBtn->Update(t);
arrowDownBtn->Update(t);
scrollbarBoxBtn->Update(t);
next = listOffset;
for(int i=0; i<PAGESIZE; i++)
{
if(next >= 0)
{
if(optionBtn[i]->GetState() == STATE_DISABLED)
{
optionBtn[i]->SetVisible(true);
optionBtn[i]->SetState(STATE_DEFAULT);
}
optionTxt[i]->SetText(options->name[next]);
optionVal[i]->SetText(options->value[next]);
optionIndex[i] = next;
next = this->FindMenuItem(next, 1);
}
else
{
optionBtn[i]->SetVisible(false);
optionBtn[i]->SetState(STATE_DISABLED);
}
if(focus)
{
if(i != selectedItem && optionBtn[i]->GetState() == STATE_SELECTED)
optionBtn[i]->ResetState();
else if(i == selectedItem && optionBtn[i]->GetState() == STATE_DEFAULT)
optionBtn[selectedItem]->SetState(STATE_SELECTED);
}
optionBtn[i]->Update(t);
if(optionBtn[i]->GetState() == STATE_SELECTED)
{
selectedItem = i;
}
}
// pad/joystick navigation
if(!focus)
return; // skip navigation
if(t->Down() || arrowDownBtn->GetState() == STATE_CLICKED)
{
next = this->FindMenuItem(optionIndex[selectedItem], 1);
if(next >= 0)
{
if(selectedItem == PAGESIZE-1)
{
// move list down by 1
listOffset = this->FindMenuItem(listOffset, 1);
}
else if(optionBtn[selectedItem+1]->IsVisible())
{
optionBtn[selectedItem]->ResetState();
optionBtn[selectedItem+1]->SetState(STATE_SELECTED);
selectedItem++;
}
}
arrowDownBtn->ResetState();
}
else if(t->Up() || arrowUpBtn->GetState() == STATE_CLICKED)
{
prev = this->FindMenuItem(optionIndex[selectedItem], -1);
if(prev >= 0)
{
if(selectedItem == 0)
{
// move list up by 1
listOffset = prev;
}
else
{
optionBtn[selectedItem]->ResetState();
optionBtn[selectedItem-1]->SetState(STATE_SELECTED);
selectedItem--;
}
}
arrowUpBtn->ResetState();
}
if(updateCB)
updateCB(this);
}

View File

@ -1,420 +0,0 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Tantric February 2009
*
* gui_savebrowser.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
#include "filebrowser.h"
/**
* Constructor for the GuiSaveBrowser class.
*/
GuiSaveBrowser::GuiSaveBrowser(int w, int h, SaveList * s, int a)
{
width = w;
height = h;
saves = s;
action = a;
selectable = true;
if(action == 0) // save
listOffset = 0;
else
listOffset = -2;
selectedItem = 0;
focus = 0; // allow focus
trigA = new GuiTrigger;
if(GCSettings.WiimoteOrientation)
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
else
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
btnSoundOver = new GuiSound(button_over_pcm, button_over_pcm_size, SOUND_PCM);
btnSoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, SOUND_PCM);
gameSave = new GuiImageData(button_gamesave_png);
gameSaveOver = new GuiImageData(button_gamesave_over_png);
gameSaveBlank = new GuiImageData(button_gamesave_blank_png);
scrollbar = new GuiImageData(scrollbar_png);
scrollbarImg = new GuiImage(scrollbar);
scrollbarImg->SetParent(this);
scrollbarImg->SetAlignment(ALIGN_RIGHT, ALIGN_TOP);
scrollbarImg->SetPosition(0, 30);
arrowDown = new GuiImageData(scrollbar_arrowdown_png);
arrowDownImg = new GuiImage(arrowDown);
arrowDownOver = new GuiImageData(scrollbar_arrowdown_over_png);
arrowDownOverImg = new GuiImage(arrowDownOver);
arrowUp = new GuiImageData(scrollbar_arrowup_png);
arrowUpImg = new GuiImage(arrowUp);
arrowUpOver = new GuiImageData(scrollbar_arrowup_over_png);
arrowUpOverImg = new GuiImage(arrowUpOver);
scrollbarBox = new GuiImageData(scrollbar_box_png);
scrollbarBoxImg = new GuiImage(scrollbarBox);
scrollbarBoxOver = new GuiImageData(scrollbar_box_over_png);
scrollbarBoxOverImg = new GuiImage(scrollbarBoxOver);
arrowUpBtn = new GuiButton(arrowUpImg->GetWidth(), arrowUpImg->GetHeight());
arrowUpBtn->SetParent(this);
arrowUpBtn->SetImage(arrowUpImg);
arrowUpBtn->SetImageOver(arrowUpOverImg);
arrowUpBtn->SetAlignment(ALIGN_RIGHT, ALIGN_TOP);
arrowUpBtn->SetSelectable(false);
arrowUpBtn->SetTrigger(trigA);
arrowUpBtn->SetSoundOver(btnSoundOver);
arrowUpBtn->SetSoundClick(btnSoundClick);
arrowDownBtn = new GuiButton(arrowDownImg->GetWidth(), arrowDownImg->GetHeight());
arrowDownBtn->SetParent(this);
arrowDownBtn->SetImage(arrowDownImg);
arrowDownBtn->SetImageOver(arrowDownOverImg);
arrowDownBtn->SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM);
arrowDownBtn->SetSelectable(false);
arrowDownBtn->SetTrigger(trigA);
arrowDownBtn->SetSoundOver(btnSoundOver);
arrowDownBtn->SetSoundClick(btnSoundClick);
scrollbarBoxBtn = new GuiButton(scrollbarBoxImg->GetWidth(), scrollbarBoxImg->GetHeight());
scrollbarBoxBtn->SetParent(this);
scrollbarBoxBtn->SetImage(scrollbarBoxImg);
scrollbarBoxBtn->SetImageOver(scrollbarBoxOverImg);
scrollbarBoxBtn->SetAlignment(ALIGN_RIGHT, ALIGN_TOP);
scrollbarBoxBtn->SetSelectable(false);
for(int i=0; i<SAVELISTSIZE; i++)
{
saveDate[i] = new GuiText(NULL, 22, (GXColor){0, 0, 0, 0xff});
saveDate[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP);
saveDate[i]->SetPosition(80,5);
saveTime[i] = new GuiText(NULL, 22, (GXColor){0, 0, 0, 0xff});
saveTime[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP);
saveTime[i]->SetPosition(80,27);
saveType[i] = new GuiText(NULL, 22, (GXColor){0, 0, 0, 0xff});
saveType[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP);
saveType[i]->SetPosition(80,50);
saveBgImg[i] = new GuiImage(gameSave);
saveBgOverImg[i] = new GuiImage(gameSaveOver);
savePreviewImg[i] = new GuiImage(gameSaveBlank);
savePreviewImg[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
savePreviewImg[i]->SetPosition(5,0);
saveBtn[i] = new GuiButton(saveBgImg[i]->GetWidth(),saveBgImg[i]->GetHeight());
saveBtn[i]->SetParent(this);
saveBtn[i]->SetLabel(saveDate[i], 0);
saveBtn[i]->SetLabel(saveTime[i], 1);
saveBtn[i]->SetLabel(saveType[i], 2);
saveBtn[i]->SetImage(saveBgImg[i]);
saveBtn[i]->SetImageOver(saveBgOverImg[i]);
saveBtn[i]->SetIcon(savePreviewImg[i]);
saveBtn[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP);
saveBtn[i]->SetPosition(257*(i % 2),87*(i/2));
saveBtn[i]->SetTrigger(trigA);
saveBtn[i]->SetState(STATE_DISABLED);
saveBtn[i]->SetEffectGrow();
saveBtn[i]->SetVisible(false);
saveBtn[i]->SetSoundOver(btnSoundOver);
saveBtn[i]->SetSoundClick(btnSoundClick);
}
}
/**
* Destructor for the GuiSaveBrowser class.
*/
GuiSaveBrowser::~GuiSaveBrowser()
{
delete arrowUpBtn;
delete arrowDownBtn;
delete scrollbarBoxBtn;
delete scrollbarImg;
delete arrowDownImg;
delete arrowDownOverImg;
delete arrowUpImg;
delete arrowUpOverImg;
delete scrollbarBoxImg;
delete scrollbarBoxOverImg;
delete gameSave;
delete gameSaveOver;
delete gameSaveBlank;
delete scrollbar;
delete arrowDown;
delete arrowDownOver;
delete arrowUp;
delete arrowUpOver;
delete scrollbarBox;
delete scrollbarBoxOver;
delete btnSoundOver;
delete btnSoundClick;
delete trigA;
for(int i=0; i<SAVELISTSIZE; i++)
{
delete saveBtn[i];
delete saveDate[i];
delete saveTime[i];
delete saveType[i];
delete saveBgImg[i];
delete saveBgOverImg[i];
delete savePreviewImg[i];
}
}
void GuiSaveBrowser::SetFocus(int f)
{
focus = f;
for(int i=0; i<SAVELISTSIZE; i++)
saveBtn[i]->ResetState();
if(f == 1)
saveBtn[selectedItem]->SetState(STATE_SELECTED);
}
void GuiSaveBrowser::ResetState()
{
if(state != STATE_DISABLED)
state = STATE_DEFAULT;
for(int i=0; i<SAVELISTSIZE; i++)
{
saveBtn[i]->ResetState();
}
}
int GuiSaveBrowser::GetClickedSave()
{
int found = -1;
for(int i=0; i<SAVELISTSIZE; i++)
{
if(saveBtn[i]->GetState() == STATE_CLICKED)
{
saveBtn[i]->SetState(STATE_SELECTED);
found = i;
break;
}
}
return found;
}
/**
* Draw the button on screen
*/
void GuiSaveBrowser::Draw()
{
if(!this->IsVisible())
return;
for(int i=0; i<SAVELISTSIZE; i++)
saveBtn[i]->Draw();
scrollbarImg->Draw();
arrowUpBtn->Draw();
arrowDownBtn->Draw();
scrollbarBoxBtn->Draw();
this->UpdateEffects();
}
void GuiSaveBrowser::Update(GuiTrigger * t)
{
if(state == STATE_DISABLED || !t)
return;
int i, len;
char savetext[50];
// update the location of the scroll box based on the position in the option list
int position;
if(action == 0)
position = 136*(listOffset+selectedItem)/saves->length;
else
position = 136*(listOffset+selectedItem+2)/saves->length;
if(position > 130)
position = 136;
scrollbarBoxBtn->SetPosition(0,position+36);
arrowUpBtn->Update(t);
arrowDownBtn->Update(t);
scrollbarBoxBtn->Update(t);
// pad/joystick navigation
if(!focus)
goto endNavigation; // skip navigation
if(t->Right())
{
if(selectedItem == SAVELISTSIZE-1)
{
if(listOffset + SAVELISTSIZE < saves->length)
{
// move list down by 1 row
listOffset += 2;
selectedItem -= 1;
}
}
else if(saveBtn[selectedItem+1]->IsVisible())
{
saveBtn[selectedItem]->ResetState();
saveBtn[selectedItem+1]->SetState(STATE_SELECTED);
selectedItem += 1;
}
}
else if(t->Left())
{
if(selectedItem == 0)
{
if((listOffset - 2 >= 0 && action == 0) ||
(listOffset - 2 >= -2 && action == 1))
{
// move list up by 1
listOffset -= 2;
selectedItem = SAVELISTSIZE-1;
}
}
else
{
selectedItem -= 1;
}
}
else if(t->Down() || arrowDownBtn->GetState() == STATE_CLICKED)
{
if(selectedItem >= SAVELISTSIZE-2)
{
if(listOffset + SAVELISTSIZE + 1 < saves->length)
{
listOffset += 2;
}
else if(listOffset + SAVELISTSIZE < saves->length)
{
listOffset += 2;
if(selectedItem == SAVELISTSIZE-1)
selectedItem -= 1;
}
}
else if(saveBtn[selectedItem+2]->IsVisible())
{
selectedItem += 2;
}
arrowDownBtn->ResetState();
}
else if(t->Up() || arrowUpBtn->GetState() == STATE_CLICKED)
{
if(selectedItem < 2)
{
if((listOffset - 2 >= 0 && action == 0) ||
(listOffset - 2 >= -2 && action == 1))
{
// move list up by 1
listOffset -= 2;
}
}
else
{
selectedItem -= 2;
}
arrowUpBtn->ResetState();
}
endNavigation:
for(i=0; i<SAVELISTSIZE; i++)
{
if(listOffset+i < 0 && action == 1)
{
saveDate[0]->SetText(NULL);
saveDate[1]->SetText(NULL);
saveTime[0]->SetText("New SRAM");
saveTime[1]->SetText("New Snapshot");
saveType[0]->SetText(NULL);
saveType[1]->SetText(NULL);
savePreviewImg[0]->SetImage(gameSaveBlank);
savePreviewImg[1]->SetImage(gameSaveBlank);
savePreviewImg[0]->SetScale(1);
savePreviewImg[1]->SetScale(1);
saveBtn[0]->SetVisible(true);
saveBtn[1]->SetVisible(true);
if(saveBtn[0]->GetState() == STATE_DISABLED)
saveBtn[0]->SetState(STATE_DEFAULT);
if(saveBtn[1]->GetState() == STATE_DISABLED)
saveBtn[1]->SetState(STATE_DEFAULT);
}
else if(listOffset+i < saves->length)
{
if(saveBtn[i]->GetState() == STATE_DISABLED)
{
saveBtn[i]->SetVisible(true);
saveBtn[i]->SetState(STATE_DEFAULT);
}
saveDate[i]->SetText(saves->date[listOffset+i]);
saveTime[i]->SetText(saves->time[listOffset+i]);
if(saves->type[listOffset+i] == FILE_SRAM)
sprintf(savetext, "SRAM");
else
sprintf(savetext, "Snapshot");
len = strlen(saves->filename[listOffset+i]);
if(len > 10 &&
((saves->filename[listOffset+i][len-8] == 'A' &&
saves->filename[listOffset+i][len-7] == 'u' &&
saves->filename[listOffset+i][len-6] == 't' &&
saves->filename[listOffset+i][len-5] == 'o') ||
saves->filename[listOffset+i][len-5] == '0')
)
{
strcat(savetext, " (Auto)");
}
saveType[i]->SetText(savetext);
if(saves->previewImg[listOffset+i] != NULL)
{
savePreviewImg[i]->SetImage(saves->previewImg[listOffset+i]);
savePreviewImg[i]->SetScale(0.1);
}
else
{
savePreviewImg[i]->SetImage(gameSaveBlank);
savePreviewImg[i]->SetScale(1);
}
}
else
{
saveBtn[i]->SetVisible(false);
saveBtn[i]->SetState(STATE_DISABLED);
}
if(focus)
{
if(i != selectedItem && saveBtn[i]->GetState() == STATE_SELECTED)
saveBtn[i]->ResetState();
else if(i == selectedItem && saveBtn[i]->GetState() == STATE_DEFAULT)
saveBtn[selectedItem]->SetState(STATE_SELECTED);
}
saveBtn[i]->Update(t);
if(saveBtn[i]->GetState() == STATE_SELECTED)
selectedItem = i;
}
if(updateCB)
updateCB(this);
}

View File

@ -1,155 +0,0 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Tantric February 2009
*
* gui_sound.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
/**
* Constructor for the GuiSound class.
*/
GuiSound::GuiSound(const u8 * snd, s32 len, int t)
{
sound = snd;
length = len;
type = t;
voice = -1;
volume = 100;
loop = false;
}
/**
* Destructor for the GuiSound class.
*/
GuiSound::~GuiSound()
{
#ifndef NO_SOUND
if(type == SOUND_OGG)
StopOgg();
#endif
}
void GuiSound::Play()
{
#ifndef NO_SOUND
int vol;
switch(type)
{
case SOUND_PCM:
vol = 255*(volume/100.0)*(GCSettings.SFXVolume/100.0);
voice = ASND_GetFirstUnusedVoice();
if(voice >= 0)
ASND_SetVoice(voice, VOICE_STEREO_16BIT, 48000, 0,
(u8 *)sound, length, vol, vol, NULL);
break;
case SOUND_OGG:
voice = 0;
if(loop)
PlayOgg(mem_open((char *)sound, length), 0, OGG_INFINITE_TIME);
else
PlayOgg(mem_open((char *)sound, length), 0, OGG_ONE_TIME);
SetVolumeOgg(255*(volume/100.0));
break;
}
#endif
}
void GuiSound::Stop()
{
#ifndef NO_SOUND
if(voice < 0)
return;
switch(type)
{
case SOUND_PCM:
ASND_StopVoice(voice);
break;
case SOUND_OGG:
StopOgg();
break;
}
#endif
}
void GuiSound::Pause()
{
#ifndef NO_SOUND
if(voice < 0)
return;
switch(type)
{
case SOUND_PCM:
ASND_PauseVoice(voice, 1);
break;
case SOUND_OGG:
PauseOgg(1);
break;
}
#endif
}
void GuiSound::Resume()
{
#ifndef NO_SOUND
if(voice < 0)
return;
switch(type)
{
case SOUND_PCM:
ASND_PauseVoice(voice, 0);
break;
case SOUND_OGG:
PauseOgg(0);
break;
}
#endif
}
bool GuiSound::IsPlaying()
{
if(ASND_StatusVoice(voice) == SND_WORKING || ASND_StatusVoice(voice) == SND_WAITING)
return true;
else
return false;
}
void GuiSound::SetVolume(int vol)
{
#ifndef NO_SOUND
volume = vol;
if(voice < 0)
return;
int newvol = 255*(volume/100.0)*(GCSettings.SFXVolume/100.0);
switch(type)
{
case SOUND_PCM:
ASND_ChangeVolumeVoice(voice, newvol, newvol);
break;
case SOUND_OGG:
SetVolumeOgg(255*(volume/100.0));
break;
}
#endif
}
void GuiSound::SetLoop(bool l)
{
loop = l;
}

View File

@ -1,234 +0,0 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Tantric February 2009
*
* gui_text.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
static int currentSize = 0;
static int presetSize = 0;
static int presetMaxWidth = 0;
static int presetAlignmentHor = 0;
static int presetAlignmentVert = 0;
static u16 presetStyle = 0;
static GXColor presetColor = (GXColor){255, 255, 255, 255};
/**
* Constructor for the GuiText class.
*/
GuiText::GuiText(const char * t, int s, GXColor c)
{
text = NULL;
size = s;
color = c;
alpha = c.a;
style = FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE;
maxWidth = 0;
alignmentHor = ALIGN_CENTRE;
alignmentVert = ALIGN_MIDDLE;
if(t)
text = fontSystem->charToWideChar((char *)t);
}
/**
* Constructor for the GuiText class, uses presets
*/
GuiText::GuiText(const char * t)
{
text = NULL;
size = presetSize;
color = presetColor;
alpha = presetColor.a;
style = presetStyle;
maxWidth = presetMaxWidth;
alignmentHor = presetAlignmentHor;
alignmentVert = presetAlignmentVert;
if(t)
text = fontSystem->charToWideChar((char *)t);
}
/**
* Destructor for the GuiText class.
*/
GuiText::~GuiText()
{
if(text)
{
delete text;
text = NULL;
}
}
void GuiText::SetText(const char * t)
{
if(text)
delete text;
text = NULL;
if(t)
text = fontSystem->charToWideChar((char *)t);
}
void GuiText::SetPresets(int sz, GXColor c, int w, u16 s, int h, int v)
{
presetSize = sz;
presetColor = c;
presetStyle = s;
presetMaxWidth = w;
presetAlignmentHor = h;
presetAlignmentVert = v;
}
void GuiText::SetFontSize(int s)
{
size = s;
}
void GuiText::SetMaxWidth(int w)
{
maxWidth = w;
}
void GuiText::SetColor(GXColor c)
{
color = c;
alpha = c.a;
}
void GuiText::SetStyle(u16 s)
{
style = s;
}
void GuiText::SetAlignment(int hor, int vert)
{
style = 0;
switch(hor)
{
case ALIGN_LEFT:
style |= FTGX_JUSTIFY_LEFT;
break;
case ALIGN_RIGHT:
style |= FTGX_JUSTIFY_RIGHT;
break;
default:
style |= FTGX_JUSTIFY_CENTER;
break;
}
switch(vert)
{
case ALIGN_TOP:
style |= FTGX_ALIGN_TOP;
break;
case ALIGN_BOTTOM:
style |= FTGX_ALIGN_BOTTOM;
break;
default:
style |= FTGX_ALIGN_MIDDLE;
break;
}
alignmentHor = hor;
alignmentVert = vert;
}
/**
* Draw the text on screen
*/
void GuiText::Draw()
{
if(!text)
return;
if(!this->IsVisible())
return;
GXColor c = color;
c.a = this->GetAlpha();
int newSize = size*this->GetScale();
if(newSize != currentSize)
{
fontSystem->changeSize(newSize);
currentSize = newSize;
}
int voffset = 0;
if(alignmentVert == ALIGN_MIDDLE)
voffset = -newSize/2 + 2;
if(maxWidth > 0) // text wrapping
{
int lineheight = newSize + 6;
int strlen = wcslen(text);
int i = 0;
int ch = 0;
int linenum = 0;
int lastSpace = -1;
int lastSpaceIndex = -1;
wchar_t * tmptext[20];
while(ch < strlen)
{
if(i == 0)
tmptext[linenum] = new wchar_t[strlen + 1];
tmptext[linenum][i] = text[ch];
tmptext[linenum][i+1] = 0;
if(text[ch] == ' ' || ch == strlen-1)
{
if(fontSystem->getWidth(tmptext[linenum]) >= maxWidth)
{
if(lastSpace >= 0)
{
tmptext[linenum][lastSpaceIndex] = 0; // discard space, and everything after
ch = lastSpace; // go backwards to the last space
lastSpace = -1; // we have used this space
lastSpaceIndex = -1;
}
linenum++;
i = -1;
}
else if(ch == strlen-1)
{
linenum++;
}
}
if(text[ch] == ' ' && i >= 0)
{
lastSpace = ch;
lastSpaceIndex = i;
}
ch++;
i++;
}
if(alignmentVert == ALIGN_MIDDLE)
voffset = voffset - (lineheight*linenum)/2 + lineheight/2;
for(i=0; i < linenum; i++)
{
fontSystem->drawText(this->GetLeft(), this->GetTop()+voffset+i*lineheight, tmptext[i], c, style);
delete tmptext[i];
}
}
else
{
fontSystem->drawText(this->GetLeft(), this->GetTop()+voffset, text, c, style);
}
this->UpdateEffects();
}

View File

@ -75,8 +75,6 @@ void GuiTrigger::SetButtonOnlyInFocusTrigger(s32 ch, u32 wiibtns, u16 gcbtns)
s8 GuiTrigger::WPAD_Stick(u8 right, int axis) s8 GuiTrigger::WPAD_Stick(u8 right, int axis)
{ {
#ifdef HW_RVL
float mag = 0.0; float mag = 0.0;
float ang = 0.0; float ang = 0.0;
@ -119,10 +117,6 @@ s8 GuiTrigger::WPAD_Stick(u8 right, int axis)
val = mag * cos((PI * ang)/180.0f); val = mag * cos((PI * ang)/180.0f);
return (s8)(val * 128.0f); return (s8)(val * 128.0f);
#else
return 0;
#endif
} }
bool GuiTrigger::Left() bool GuiTrigger::Left()
@ -130,7 +124,7 @@ bool GuiTrigger::Left()
u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_UP : WPAD_BUTTON_LEFT; u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_UP : WPAD_BUTTON_LEFT;
if((wpad.btns_d | wpad.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_LEFT) if((wpad.btns_d | wpad.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_LEFT)
|| (pad.btns_d | pad.btns_h) & PAD_BUTTON_LEFT || pad.btns_d & PAD_BUTTON_LEFT
|| pad.stickX < -PADCAL || pad.stickX < -PADCAL
|| WPAD_Stick(0,0) < -PADCAL) || WPAD_Stick(0,0) < -PADCAL)
{ {
@ -158,7 +152,7 @@ bool GuiTrigger::Right()
u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_DOWN : WPAD_BUTTON_RIGHT; u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_DOWN : WPAD_BUTTON_RIGHT;
if((wpad.btns_d | wpad.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_RIGHT) if((wpad.btns_d | wpad.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_RIGHT)
|| (pad.btns_d | pad.btns_h) & PAD_BUTTON_RIGHT || pad.btns_d & PAD_BUTTON_RIGHT
|| pad.stickX > PADCAL || pad.stickX > PADCAL
|| WPAD_Stick(0,0) > PADCAL) || WPAD_Stick(0,0) > PADCAL)
{ {
@ -186,7 +180,7 @@ bool GuiTrigger::Up()
u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_RIGHT : WPAD_BUTTON_UP; u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_RIGHT : WPAD_BUTTON_UP;
if((wpad.btns_d | wpad.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_UP) if((wpad.btns_d | wpad.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_UP)
|| (pad.btns_d | pad.btns_h) & PAD_BUTTON_UP || pad.btns_d & PAD_BUTTON_UP
|| pad.stickY > PADCAL || pad.stickY > PADCAL
|| WPAD_Stick(0,1) > PADCAL) || WPAD_Stick(0,1) > PADCAL)
{ {

View File

@ -1,404 +0,0 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Tantric February 2009
*
* gui_window.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
GuiWindow::GuiWindow()
{
width = 0;
height = 0;
focus = 0; // allow focus
}
GuiWindow::GuiWindow(int w, int h)
{
width = w;
height = h;
focus = 0; // allow focus
}
GuiWindow::~GuiWindow()
{
}
void GuiWindow::Append(GuiElement* e)
{
if (e == NULL)
return;
Remove(e);
_elements.push_back(e);
e->SetParent(this);
}
void GuiWindow::Insert(GuiElement* e, u32 index)
{
if (e == NULL || index > (_elements.size() - 1))
return;
Remove(e);
_elements.insert(_elements.begin()+index, e);
e->SetParent(this);
}
void GuiWindow::Remove(GuiElement* e)
{
if (e == NULL)
return;
for (u8 i = 0; i < _elements.size(); i++)
{
if(e == _elements.at(i))
{
_elements.erase(_elements.begin()+i);
break;
}
}
}
void GuiWindow::RemoveAll()
{
_elements.clear();
}
GuiElement* GuiWindow::GetGuiElementAt(u32 index) const
{
if (index >= _elements.size())
return NULL;
return _elements.at(index);
}
u32 GuiWindow::GetSize()
{
return _elements.size();
}
void GuiWindow::Draw()
{
if(_elements.size() == 0 || !this->IsVisible())
return;
for (u8 i = 0; i < _elements.size(); i++)
{
try { _elements.at(i)->Draw(); }
catch (exception& e) { }
}
this->UpdateEffects();
if(parentElement && state == STATE_DISABLED)
Menu_DrawRectangle(0,0,screenwidth,screenheight,(GXColor){0xbe, 0xca, 0xd5, 0x70},1);
}
void GuiWindow::ResetState()
{
if(state != STATE_DISABLED)
state = STATE_DEFAULT;
for (u8 i = 0; i < _elements.size(); i++)
{
try { _elements.at(i)->ResetState(); }
catch (exception& e) { }
}
}
void GuiWindow::SetState(int s)
{
state = s;
for (u8 i = 0; i < _elements.size(); i++)
{
try { _elements.at(i)->SetState(s); }
catch (exception& e) { }
}
}
void GuiWindow::SetVisible(bool v)
{
visible = v;
for (u8 i = 0; i < _elements.size(); i++)
{
try { _elements.at(i)->SetVisible(v); }
catch (exception& e) { }
}
}
void GuiWindow::SetFocus(int f)
{
focus = f;
if(f == 1)
this->MoveSelectionVert(1);
else
this->ResetState();
}
void GuiWindow::ChangeFocus(GuiElement* e)
{
if(parentElement)
return; // this is only intended for the main window
for (u8 i = 0; i < _elements.size(); i++)
{
if(e == _elements.at(i))
_elements.at(i)->SetFocus(1);
else if(_elements.at(i)->IsFocused() == 1)
_elements.at(i)->SetFocus(0);
}
}
void GuiWindow::ToggleFocus(GuiTrigger * t)
{
if(parentElement)
return; // this is only intended for the main window
int found = -1;
int newfocus = -1;
u8 i;
// look for currently in focus element
for (i = 0; i < _elements.size(); i++)
{
try
{
if(_elements.at(i)->IsFocused() == 1)
{
found = i;
break;
}
}
catch (exception& e) { }
}
// element with focus not found, try to give focus
if(found == -1)
{
for (i = 0; i < _elements.size(); i++)
{
try
{
if(_elements.at(i)->IsFocused() == 0 && _elements.at(i)->GetState() != STATE_DISABLED) // focus is possible (but not set)
{
_elements.at(i)->SetFocus(1); // give this element focus
break;
}
}
catch (exception& e) { }
}
}
// change focus
else if(t->wpad.btns_d & (WPAD_BUTTON_1 | WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B)
|| t->pad.btns_d & PAD_BUTTON_B)
{
for (i = found; i < _elements.size(); i++)
{
try
{
if(_elements.at(i)->IsFocused() == 0 && _elements.at(i)->GetState() != STATE_DISABLED) // focus is possible (but not set)
{
newfocus = i;
_elements.at(i)->SetFocus(1); // give this element focus
_elements.at(found)->SetFocus(0); // disable focus on other element
break;
}
}
catch (exception& e) { }
}
if(newfocus == -1)
{
for (i = 0; i < found; i++)
{
try
{
if(_elements.at(i)->IsFocused() == 0 && _elements.at(i)->GetState() != STATE_DISABLED) // focus is possible (but not set)
{
_elements.at(i)->SetFocus(1); // give this element focus
_elements.at(found)->SetFocus(0); // disable focus on other element
break;
}
}
catch (exception& e) { }
}
}
}
}
int GuiWindow::GetSelected()
{
// find selected element
int found = -1;
for (u8 i = 0; i < _elements.size(); i++)
{
try
{
if(_elements.at(i)->GetState() == STATE_SELECTED)
{
found = i;
break;
}
}
catch (exception& e) { }
}
return found;
}
// set element to left/right as selected
// there's probably a more clever way to do this, but this way works
void GuiWindow::MoveSelectionHor(int dir)
{
int found = -1;
u16 left = 0;
u16 top = 0;
u8 i = 0;
int selected = this->GetSelected();
if(selected >= 0)
{
left = _elements.at(selected)->GetLeft();
top = _elements.at(selected)->GetTop();
}
// look for a button on the same row, to the left/right
for (i = 0; i < _elements.size(); i++)
{
try
{
if(_elements.at(i)->IsSelectable())
{
if(_elements.at(i)->GetLeft()*dir > left*dir && _elements.at(i)->GetTop() == top)
{
if(found == -1)
found = i;
else if(_elements.at(i)->GetLeft()*dir < _elements.at(found)->GetLeft()*dir)
found = i; // this is a better match
}
}
}
catch (exception& e) { }
}
if(found >= 0)
goto matchfound;
// match still not found, let's try the first button in the next row
for (i = 0; i < _elements.size(); i++)
{
try
{
if(_elements.at(i)->IsSelectable())
{
if(_elements.at(i)->GetTop()*dir > top*dir)
{
if(found == -1)
found = i;
else if(_elements.at(i)->GetTop()*dir < _elements.at(found)->GetTop()*dir)
found = i; // this is a better match
else if(_elements.at(i)->GetTop()*dir == _elements.at(found)->GetTop()*dir
&&
_elements.at(i)->GetLeft()*dir < _elements.at(found)->GetLeft()*dir)
found = i; // this is a better match
}
}
}
catch (exception& e) { }
}
// match found
matchfound:
if(found >= 0)
{
_elements.at(found)->SetState(STATE_SELECTED);
if(selected >= 0)
_elements.at(selected)->ResetState();
}
}
void GuiWindow::MoveSelectionVert(int dir)
{
int found = -1;
u16 left = 0;
u16 top = 0;
u8 i = 0;
int selected = this->GetSelected();
if(selected >= 0)
{
left = _elements.at(selected)->GetLeft();
top = _elements.at(selected)->GetTop();
}
// look for a button above/below, with the least horizontal difference
for (i = 0; i < _elements.size(); i++)
{
try
{
if(_elements.at(i)->IsSelectable())
{
if(_elements.at(i)->GetTop()*dir > top*dir)
{
if(found == -1)
found = i;
else if(_elements.at(i)->GetTop()*dir < _elements.at(found)->GetTop()*dir)
found = i; // this is a better match
else if(_elements.at(i)->GetTop()*dir == _elements.at(found)->GetTop()*dir
&&
abs(_elements.at(i)->GetLeft() - left) <
abs(_elements.at(found)->GetLeft() - left))
found = i;
}
}
}
catch (exception& e) { }
}
if(found >= 0)
goto matchfound;
// match found
matchfound:
if(found >= 0)
{
_elements.at(found)->SetState(STATE_SELECTED);
if(selected >= 0)
_elements.at(selected)->ResetState();
}
}
void GuiWindow::Update(GuiTrigger * t)
{
if(_elements.size() == 0 || (state == STATE_DISABLED && parentElement))
return;
for (u8 i = 0; i < _elements.size(); i++)
{
try { _elements.at(i)->Update(t); }
catch (exception& e) { }
}
this->ToggleFocus(t);
if(focus) // only send actions to this window if it's in focus
{
// pad/joystick navigation
if(t->Right())
this->MoveSelectionHor(1);
else if(t->Left())
this->MoveSelectionHor(-1);
else if(t->Down())
this->MoveSelectionVert(1);
else if(t->Up())
this->MoveSelectionVert(-1);
}
if(updateCB)
updateCB(this);
}

View File

@ -13,14 +13,16 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <ogcsys.h> #include <ogcsys.h>
#include <network.h> #include <network.h>
#include <ogc/lwp_watchdog.h> #include <ogc/lwp_watchdog.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/errno.h> #include <sys/errno.h>
#include <fcntl.h> #include <fcntl.h>
#include "menu.h" #include "menudraw.h"
#include "http.h" #include "http.h"
static s32 tcp_socket(void) static s32 tcp_socket(void)
@ -414,7 +416,6 @@ bool http_request(const char *url, FILE * hfile, u8 * buffer,
ShowProgress("Downloading...", (content_length - bytesLeft), ShowProgress("Downloading...", (content_length - bytesLeft),
content_length); content_length);
} }
CancelAction();
} }
if (!b || !res) if (!b || !res)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 B

19212
source/ngc/images/bg.h Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 843 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 768 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 792 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 764 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 842 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 776 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 821 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 775 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 710 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 546 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 524 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 632 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 599 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 714 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 777 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 270 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 733 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 700 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 739 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 481 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -25,29 +25,26 @@
#include "gameinput.h" #include "gameinput.h"
#include "vbasupport.h" #include "vbasupport.h"
#include "wiiusbsupport.h" #include "wiiusbsupport.h"
#include "gui/gui.h"
#include "gba/GBA.h" #include "gba/GBA.h"
#include "gba/bios.h" #include "gba/bios.h"
#include "gba/GBAinline.h" #include "gba/GBAinline.h"
extern bool InMenu;
int rumbleRequest[4] = {0,0,0,0}; int rumbleRequest[4] = {0,0,0,0};
GuiTrigger userInput[4];
#ifdef HW_RVL
static int rumbleCount[4] = {0,0,0,0}; static int rumbleCount[4] = {0,0,0,0};
#endif
bool cartridgeRumble = false; bool cartridgeRumble = false;
int gameRumbleCount = 0, menuRumbleCount = 0, rumbleCountAlready = 0; int gameRumbleCount = 0, menuRumbleCount = 0, rumbleCountAlready = 0;
unsigned int vbapadmap[10]; // VBA controller buttons unsigned int vbapadmap[10]; // VBA controller buttons
u32 btnmap[5][10]; // button mapping unsigned int gcpadmap[10]; // Gamecube controller Padmap
unsigned int wmpadmap[10]; // Wiimote Padmap
unsigned int ccpadmap[10]; // Classic Controller Padmap
unsigned int ncpadmap[10]; // Nunchuk + wiimote Padmap
unsigned int kbpadmap[10]; // Keyboard Padmap
void ResetControls() void ResetControls()
{ {
memset(btnmap, 0, sizeof(btnmap)); int i = 0;
int i;
// VBA controller buttons // VBA controller buttons
// All other pads are mapped to this // All other pads are mapped to this
@ -65,72 +62,70 @@ void ResetControls()
/*** Gamecube controller Padmap ***/ /*** Gamecube controller Padmap ***/
i=0; i=0;
btnmap[CTRLR_GCPAD][i++] = PAD_BUTTON_B; gcpadmap[i++] = PAD_BUTTON_B;
btnmap[CTRLR_GCPAD][i++] = PAD_BUTTON_A; gcpadmap[i++] = PAD_BUTTON_A;
btnmap[CTRLR_GCPAD][i++] = PAD_TRIGGER_Z; gcpadmap[i++] = PAD_TRIGGER_Z;
btnmap[CTRLR_GCPAD][i++] = PAD_BUTTON_START; gcpadmap[i++] = PAD_BUTTON_START;
btnmap[CTRLR_GCPAD][i++] = PAD_BUTTON_UP; gcpadmap[i++] = PAD_BUTTON_UP;
btnmap[CTRLR_GCPAD][i++] = PAD_BUTTON_DOWN; gcpadmap[i++] = PAD_BUTTON_DOWN;
btnmap[CTRLR_GCPAD][i++] = PAD_BUTTON_LEFT; gcpadmap[i++] = PAD_BUTTON_LEFT;
btnmap[CTRLR_GCPAD][i++] = PAD_BUTTON_RIGHT; gcpadmap[i++] = PAD_BUTTON_RIGHT;
btnmap[CTRLR_GCPAD][i++] = PAD_TRIGGER_L; gcpadmap[i++] = PAD_TRIGGER_L;
btnmap[CTRLR_GCPAD][i++] = PAD_TRIGGER_R; gcpadmap[i++] = PAD_TRIGGER_R;
/*** Wiimote Padmap ***/ /*** Wiimote Padmap ***/
i=0; i=0;
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_1; wmpadmap[i++] = WPAD_BUTTON_1;
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_2; wmpadmap[i++] = WPAD_BUTTON_2;
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_MINUS; wmpadmap[i++] = WPAD_BUTTON_MINUS;
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_PLUS; wmpadmap[i++] = WPAD_BUTTON_PLUS;
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_RIGHT; wmpadmap[i++] = WPAD_BUTTON_RIGHT;
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_LEFT; wmpadmap[i++] = WPAD_BUTTON_LEFT;
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_UP; wmpadmap[i++] = WPAD_BUTTON_UP;
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_DOWN; wmpadmap[i++] = WPAD_BUTTON_DOWN;
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_B; wmpadmap[i++] = WPAD_BUTTON_B;
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_A; wmpadmap[i++] = WPAD_BUTTON_A;
/*** Classic Controller Padmap ***/ /*** Classic Controller Padmap ***/
i=0; i=0;
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_Y; ccpadmap[i++] = WPAD_CLASSIC_BUTTON_Y;
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_B; ccpadmap[i++] = WPAD_CLASSIC_BUTTON_B;
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_MINUS; ccpadmap[i++] = WPAD_CLASSIC_BUTTON_MINUS;
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_PLUS; ccpadmap[i++] = WPAD_CLASSIC_BUTTON_PLUS;
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_UP; ccpadmap[i++] = WPAD_CLASSIC_BUTTON_UP;
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_DOWN; ccpadmap[i++] = WPAD_CLASSIC_BUTTON_DOWN;
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_LEFT; ccpadmap[i++] = WPAD_CLASSIC_BUTTON_LEFT;
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_RIGHT; ccpadmap[i++] = WPAD_CLASSIC_BUTTON_RIGHT;
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_FULL_L; ccpadmap[i++] = WPAD_CLASSIC_BUTTON_FULL_L;
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_FULL_R; ccpadmap[i++] = WPAD_CLASSIC_BUTTON_FULL_R;
/*** Nunchuk + wiimote Padmap ***/ /*** Nunchuk + wiimote Padmap ***/
i=0; i=0;
btnmap[CTRLR_NUNCHUK][i++] = WPAD_NUNCHUK_BUTTON_C; ncpadmap[i++] = WPAD_NUNCHUK_BUTTON_C;
btnmap[CTRLR_NUNCHUK][i++] = WPAD_NUNCHUK_BUTTON_Z; ncpadmap[i++] = WPAD_NUNCHUK_BUTTON_Z;
btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_MINUS; ncpadmap[i++] = WPAD_BUTTON_MINUS;
btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_PLUS; ncpadmap[i++] = WPAD_BUTTON_PLUS;
btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_UP; ncpadmap[i++] = WPAD_BUTTON_UP;
btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_DOWN; ncpadmap[i++] = WPAD_BUTTON_DOWN;
btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_LEFT; ncpadmap[i++] = WPAD_BUTTON_LEFT;
btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_RIGHT; ncpadmap[i++] = WPAD_BUTTON_RIGHT;
btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_2; ncpadmap[i++] = WPAD_BUTTON_2;
btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_1; ncpadmap[i++] = WPAD_BUTTON_1;
/*** Keyboard map ***/ /*** Keyboard map ***/
i=0; i=0;
btnmap[CTRLR_KEYBOARD][i++] = KB_X; // VBA stupidly has B on the right instead of left kbpadmap[i++] = KB_X; // VBA stupidly has B on the right instead of left
btnmap[CTRLR_KEYBOARD][i++] = KB_Z; kbpadmap[i++] = KB_Z;
btnmap[CTRLR_KEYBOARD][i++] = KB_BKSP; kbpadmap[i++] = KB_BKSP;
btnmap[CTRLR_KEYBOARD][i++] = KB_ENTER; kbpadmap[i++] = KB_ENTER;
btnmap[CTRLR_KEYBOARD][i++] = KB_UP; kbpadmap[i++] = KB_UP;
btnmap[CTRLR_KEYBOARD][i++] = KB_DOWN; kbpadmap[i++] = KB_DOWN;
btnmap[CTRLR_KEYBOARD][i++] = KB_LEFT; kbpadmap[i++] = KB_LEFT;
btnmap[CTRLR_KEYBOARD][i++] = KB_RIGHT; kbpadmap[i++] = KB_RIGHT;
btnmap[CTRLR_KEYBOARD][i++] = KB_A; kbpadmap[i++] = KB_A;
btnmap[CTRLR_KEYBOARD][i++] = KB_S; kbpadmap[i++] = KB_S;
} }
#ifdef HW_RVL
/**************************************************************************** /****************************************************************************
* ShutoffRumble * ShutoffRumble
***************************************************************************/ ***************************************************************************/
@ -141,10 +136,8 @@ void ShutoffRumble()
for(int i=0;i<4;i++) for(int i=0;i<4;i++)
{ {
WPAD_Rumble(i, 0); WPAD_Rumble(i, 0);
rumbleCount[i] = 0;
} }
#endif #endif
PAD_ControlMotor(PAD_CHAN0, PAD_MOTOR_STOP);
} }
/**************************************************************************** /****************************************************************************
@ -170,19 +163,17 @@ void DoRumble(int i)
WPAD_Rumble(i, 0); // rumble off WPAD_Rumble(i, 0); // rumble off
} }
} }
#endif
static void updateRumble() static void updateRumble() {
{
bool r = false; bool r = false;
if (ConfigRequested) r = (menuRumbleCount > 0); if (InMenu) r = (menuRumbleCount > 0);
else r = cartridgeRumble || (gameRumbleCount > 0) || (menuRumbleCount > 0); else r = cartridgeRumble || (gameRumbleCount > 0) || (menuRumbleCount > 0);
#ifdef HW_RVL #ifdef HW_RVL
// Rumble wii remote 0 // Rumble wii remote 0
WPAD_Rumble(0, r); WPAD_Rumble(0, r);
#endif #endif
PAD_ControlMotor(PAD_CHAN0, r?PAD_MOTOR_RUMBLE:PAD_MOTOR_STOP); PAD_ControlMotor(PAD_CHAN0, PAD_MOTOR_RUMBLE);
} }
void updateRumbleFrame() { void updateRumbleFrame() {
@ -195,7 +186,7 @@ void updateRumbleFrame() {
if (rumbleCountAlready > 50+10) if (rumbleCountAlready > 50+10)
rumbleCountAlready = 0; rumbleCountAlready = 0;
else rumbleCountAlready++; else rumbleCountAlready++;
} else if (ConfigRequested) { } else if (InMenu) {
if (menuRumbleCount>0) if (menuRumbleCount>0)
rumbleCountAlready++; rumbleCountAlready++;
} else { } else {
@ -203,7 +194,7 @@ void updateRumbleFrame() {
rumbleCountAlready++; rumbleCountAlready++;
} }
updateRumble(); updateRumble();
if (gameRumbleCount>0 && !ConfigRequested) gameRumbleCount--; if (gameRumbleCount>0 && !InMenu) gameRumbleCount--;
if (menuRumbleCount>0) menuRumbleCount--; if (menuRumbleCount>0) menuRumbleCount--;
} }
@ -584,7 +575,7 @@ u32 DecodeKeyboard(unsigned short pad)
#ifdef HW_RVL #ifdef HW_RVL
for (int i = 0; i < MAXJP; i++) for (int i = 0; i < MAXJP; i++)
{ {
if (DownUsbKeys[btnmap[CTRLR_KEYBOARD][i]]) // keyboard if (DownUsbKeys[kbpadmap[i]]) // keyboard
J |= vbapadmap[i]; J |= vbapadmap[i];
} }
#endif #endif
@ -597,7 +588,7 @@ u32 DecodeGamecube(unsigned short pad)
u32 jp = PAD_ButtonsHeld(pad); u32 jp = PAD_ButtonsHeld(pad);
for (int i = 0; i < MAXJP; i++) for (int i = 0; i < MAXJP; i++)
{ {
if (jp & btnmap[CTRLR_GCPAD][i]) if (jp & gcpadmap[i])
J |= vbapadmap[i]; J |= vbapadmap[i];
} }
return J; return J;
@ -610,7 +601,7 @@ u32 DecodeWiimote(unsigned short pad)
WPADData * wp = WPAD_Data(pad); WPADData * wp = WPAD_Data(pad);
for (int i = 0; i < MAXJP; i++) for (int i = 0; i < MAXJP; i++)
{ {
if ( (wp->exp.type == WPAD_EXP_NONE) && (wp->btns_h & btnmap[CTRLR_WIIMOTE][i]) ) if ( (wp->exp.type == WPAD_EXP_NONE) && (wp->btns_h & wmpadmap[i]) )
J |= vbapadmap[i]; J |= vbapadmap[i];
} }
#endif #endif
@ -624,7 +615,7 @@ u32 DecodeClassic(unsigned short pad)
WPADData * wp = WPAD_Data(pad); WPADData * wp = WPAD_Data(pad);
for (int i = 0; i < MAXJP; i++) for (int i = 0; i < MAXJP; i++)
{ {
if ( (wp->exp.type == WPAD_EXP_CLASSIC) && (wp->btns_h & btnmap[CTRLR_CLASSIC][i]) ) if ( (wp->exp.type == WPAD_EXP_CLASSIC) && (wp->btns_h & ccpadmap[i]) )
J |= vbapadmap[i]; J |= vbapadmap[i];
} }
#endif #endif
@ -638,7 +629,7 @@ u32 DecodeNunchuk(unsigned short pad)
WPADData * wp = WPAD_Data(pad); WPADData * wp = WPAD_Data(pad);
for (int i = 0; i < MAXJP; i++) for (int i = 0; i < MAXJP; i++)
{ {
if ( (wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & btnmap[CTRLR_NUNCHUK][i]) ) if ( (wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & ncpadmap[i]) )
J |= vbapadmap[i]; J |= vbapadmap[i];
} }
#endif #endif
@ -867,12 +858,12 @@ static u32 DecodeJoy(unsigned short pad)
for (i = 0; i < MAXJP; i++) for (i = 0; i < MAXJP; i++)
{ {
if ((jp & btnmap[CTRLR_GCPAD][i]) // gamecube controller if ((jp & gcpadmap[i]) // gamecube controller
#ifdef HW_RVL #ifdef HW_RVL
|| ( (wp->exp.type == WPAD_EXP_NONE) && (wp->btns_h & btnmap[CTRLR_WIIMOTE][i]) ) // wiimote || ( (wp->exp.type == WPAD_EXP_NONE) && (wp->btns_h & wmpadmap[i]) ) // wiimote
|| ( (wp->exp.type == WPAD_EXP_CLASSIC) && (wp->btns_h & btnmap[CTRLR_CLASSIC][i]) ) // classic controller || ( (wp->exp.type == WPAD_EXP_CLASSIC) && (wp->btns_h & ccpadmap[i]) ) // classic controller
|| ( (wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & btnmap[CTRLR_NUNCHUK][i]) ) // nunchuk + wiimote || ( (wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & ncpadmap[i]) ) // nunchuk + wiimote
|| ( (DownUsbKeys[btnmap[CTRLR_KEYBOARD][i]]) ) // keyboard || ( (DownUsbKeys[kbpadmap[i]]) ) // keyboard
#endif #endif
) )
J |= vbapadmap[i]; J |= vbapadmap[i];
@ -886,11 +877,24 @@ u32 GetJoy(int pad)
pad = 0; pad = 0;
s8 gc_px = PAD_SubStickX(0); s8 gc_px = PAD_SubStickX(0);
s8 gc_py = PAD_SubStickY(0);
#ifdef HW_RVL #ifdef HW_RVL
u32 wm_pb = WPAD_ButtonsDown(0); // wiimote / expansion button info s8 wm_sy = WPAD_Stick (0,1,1);
u32 wm_pb = WPAD_ButtonsHeld (0); // wiimote / expansion button info
#endif #endif
// Check for video zoom
if (GCSettings.Zoom)
{
if (gc_py < -36 || gc_py > 36)
zoom((float) gc_py / -36);
#ifdef HW_RVL
if (wm_sy < -36 || wm_sy> 36)
zoom ((float) wm_sy / -36);
#endif
}
// request to go back to menu // request to go back to menu
if ((gc_px < -70) if ((gc_px < -70)
#ifdef HW_RVL #ifdef HW_RVL

View File

@ -12,11 +12,10 @@
#define _INPUT_H_ #define _INPUT_H_
#include <gccore.h> #include <gccore.h>
#include <wiiuse/wpad.h>
#define PI 3.14159265f #define PI 3.14159265f
#define PADCAL 50 #define PADCAL 50
#define MAXJP 10 // # of mappable controller buttons #define MAXJP 10
#define VBA_BUTTON_A 1 #define VBA_BUTTON_A 1
#define VBA_BUTTON_B 2 #define VBA_BUTTON_B 2
@ -31,48 +30,13 @@
#define VBA_SPEED 1024 #define VBA_SPEED 1024
#define VBA_CAPTURE 2048 #define VBA_CAPTURE 2048
enum
{
TRIGGER_SIMPLE,
TRIGGER_BUTTON_ONLY,
TRIGGER_BUTTON_ONLY_IN_FOCUS
};
typedef struct _paddata {
u16 btns_d;
u16 btns_u;
u16 btns_h;
s8 stickX;
s8 stickY;
s8 substickX;
s8 substickY;
u8 triggerL;
u8 triggerR;
} PADData;
class GuiTrigger
{
public:
GuiTrigger();
~GuiTrigger();
void SetSimpleTrigger(s32 ch, u32 wiibtns, u16 gcbtns);
void SetButtonOnlyTrigger(s32 ch, u32 wiibtns, u16 gcbtns);
void SetButtonOnlyInFocusTrigger(s32 ch, u32 wiibtns, u16 gcbtns);
s8 WPAD_Stick(u8 right, int axis);
bool Left();
bool Right();
bool Up();
bool Down();
u8 type;
s32 chan;
WPADData wpad;
PADData pad;
};
extern GuiTrigger userInput[4];
extern int rumbleRequest[4]; extern int rumbleRequest[4];
extern u32 btnmap[5][10];
extern unsigned int gcpadmap[];
extern unsigned int wmpadmap[];
extern unsigned int ccpadmap[];
extern unsigned int ncpadmap[];
extern unsigned int kbpadmap[];
void ResetControls(); void ResetControls();
void ShutoffRumble(); void ShutoffRumble();

Some files were not shown because too many files have changed in this diff Show More