[1.0.9 - April 7, 2009]
* Gamecube controller should no longer rumble constantly
13
Makefile.gc
@ -29,7 +29,7 @@ INCLUDES := source/vba source/ngc source/unzip
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
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 \
|
||||
-DSDL -DNO_PNG -DHAVE_ZUTIL_H \
|
||||
-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
|
||||
#---------------------------------------------------------------------------------
|
||||
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
|
||||
@ -72,7 +72,6 @@ sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
||||
TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf)))
|
||||
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
|
||||
@ -85,8 +84,8 @@ endif
|
||||
|
||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
|
||||
$(TTFFILES:.ttf=.ttf.o) $(PNGFILES:.png=.png.o) \
|
||||
$(PCMFILES:.pcm=.pcm.o)
|
||||
$(TTFFILES:.ttf=.ttf.o) \
|
||||
$(PNGFILES:.png=.png.o)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# build a list of include paths
|
||||
@ -147,10 +146,6 @@ $(OUTPUT).elf: $(OFILES)
|
||||
@echo $(notdir $<)
|
||||
$(bin2o)
|
||||
|
||||
%.pcm.o : %.pcm
|
||||
@echo $(notdir $<)
|
||||
$(bin2o)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
|
17
Makefile.wii
@ -41,8 +41,7 @@ LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map -Wl,--cref
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -ldb -ldi -lpngu -lpng -lmxml -lmetaphrasis \
|
||||
-lfat -lwiiuse -lz -lbte -logc -lasnd -ltremor -lfreetype -ltinysmb
|
||||
LIBS := -ldi -lpngu -lpng -lmxml -lfat -lwiiuse -lz -lbte -logc -lm -lfreetype -ltinysmb
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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)))
|
||||
TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf)))
|
||||
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
|
||||
@ -87,8 +84,8 @@ endif
|
||||
|
||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
|
||||
$(TTFFILES:.ttf=.ttf.o) $(PNGFILES:.png=.png.o) \
|
||||
$(OGGFILES:.ogg=.ogg.o) $(PCMFILES:.pcm=.pcm.o)
|
||||
$(TTFFILES:.ttf=.ttf.o) \
|
||||
$(PNGFILES:.png=.png.o)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# build a list of include paths
|
||||
@ -149,14 +146,6 @@ $(OUTPUT).elf: $(OFILES)
|
||||
@echo $(notdir $<)
|
||||
$(bin2o)
|
||||
|
||||
%.ogg.o : %.ogg
|
||||
@echo $(notdir $<)
|
||||
$(bin2o)
|
||||
|
||||
%.pcm.o : %.pcm
|
||||
@echo $(notdir $<)
|
||||
$(bin2o)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
|
@ -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();
|
||||
}
|
@ -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_ */
|
@ -9,11 +9,9 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include <gccore.h>
|
||||
#include <ogcsys.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <asndlib.h>
|
||||
|
||||
#include "audio.h"
|
||||
|
||||
@ -92,34 +90,6 @@ void SetAudioRate(int 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
|
||||
***************************************************************************/
|
||||
@ -127,22 +97,8 @@ SwitchAudioMode(int mode)
|
||||
void InitialiseSound()
|
||||
{
|
||||
AUDIO_Init(NULL); // Start audio subsystem
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* 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);
|
||||
AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
|
||||
AUDIO_RegisterDMACallback(AudioPlayer);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -16,8 +16,6 @@
|
||||
void InitialiseSound();
|
||||
void StopAudio();
|
||||
void SetAudioRate(int type);
|
||||
void SwitchAudioMode(int mode);
|
||||
void ShutdownAudio();
|
||||
|
||||
class SoundWii: public SoundDriver
|
||||
{
|
||||
|
@ -25,50 +25,6 @@
|
||||
***************************************************************************/
|
||||
|
||||
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
|
||||
{
|
||||
CTRLR_NUNCHUK,
|
||||
@ -107,12 +63,56 @@ CtrlrMap ctrlr_def[5] = {
|
||||
{WPAD_CLASSIC_BUTTON_PLUS, "PLUS"},
|
||||
{WPAD_CLASSIC_BUTTON_MINUS, "MINUS"},
|
||||
{WPAD_CLASSIC_BUTTON_HOME, "HOME"},
|
||||
{WPAD_CLASSIC_BUTTON_FULL_L, "L"},
|
||||
{WPAD_CLASSIC_BUTTON_FULL_R, "R"},
|
||||
{WPAD_CLASSIC_BUTTON_FULL_L, "L TRIG"},
|
||||
{WPAD_CLASSIC_BUTTON_FULL_R, "R TRIG"},
|
||||
{WPAD_CLASSIC_BUTTON_ZL, "ZL"},
|
||||
{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
|
||||
{
|
||||
CTRLR_KEYBOARD,
|
||||
@ -250,7 +250,9 @@ CtrlrMap ctrlr_def[5] = {
|
||||
{231, "RWIN"},
|
||||
{232, "MOUSEL"},
|
||||
{233, "MOUSER"},
|
||||
{234, "MOUSEM"}
|
||||
{234, "MOUSEM"},
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -13,16 +13,14 @@
|
||||
|
||||
enum {
|
||||
CTRLR_NONE = -1,
|
||||
CTRLR_GCPAD,
|
||||
CTRLR_WIIMOTE,
|
||||
CTRLR_NUNCHUK,
|
||||
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 {
|
||||
u32 btn; // button 'id'
|
||||
char* name; // button name
|
||||
|
@ -21,11 +21,10 @@ extern "C" {
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "vba.h"
|
||||
#include "menu.h"
|
||||
#include "menudraw.h"
|
||||
#include "gcunzip.h"
|
||||
#include "filebrowser.h"
|
||||
#include "fileop.h"
|
||||
#include "filesel.h"
|
||||
#include "vba.h"
|
||||
|
||||
#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!
|
||||
* returns: 1 - ok ; 0 - error
|
||||
***************************************************************************/
|
||||
|
||||
int dvd_safe_read(void *dst_v, u32 len, u64 fileoffset)
|
||||
{
|
||||
u64 offset = dvddir + fileoffset;
|
||||
@ -318,40 +318,35 @@ getpvd ()
|
||||
*
|
||||
* Tests if a ISO9660 DVD is inserted and available, and mounts it
|
||||
***************************************************************************/
|
||||
|
||||
bool MountDVD(bool silent)
|
||||
{
|
||||
bool res = false;
|
||||
|
||||
if (getpvd())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (!getpvd())
|
||||
{
|
||||
ShowAction("Loading DVD...");
|
||||
#ifdef HW_DOL
|
||||
DVD_Mount(); // mount the DVD unit again
|
||||
#else
|
||||
#elif HW_RVL
|
||||
u32 val;
|
||||
DI_GetCoverRegister(&val);
|
||||
if(val & 0x1) // True if no disc inside, use (val & 0x2) for true if disc inside.
|
||||
{
|
||||
if(!silent)
|
||||
ErrorPrompt("No disc inserted!");
|
||||
CancelAction();
|
||||
WaitPrompt("No disc inserted!");
|
||||
return false;
|
||||
}
|
||||
DI_Mount();
|
||||
while(DI_GetStatus() & DVD_INIT) usleep(20000);
|
||||
while(DI_GetStatus() & DVD_INIT);
|
||||
#endif
|
||||
|
||||
if (getpvd())
|
||||
res = true;
|
||||
else if(!silent)
|
||||
ErrorPrompt("Invalid DVD.");
|
||||
if (!getpvd())
|
||||
{
|
||||
if(!silent)
|
||||
WaitPrompt ("Invalid DVD.");
|
||||
return false;
|
||||
}
|
||||
CancelAction();
|
||||
return res;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -360,6 +355,7 @@ bool MountDVD(bool silent)
|
||||
* Support function to return the next file entry, if any
|
||||
* Declared static to avoid accidental external entry.
|
||||
***************************************************************************/
|
||||
|
||||
static int
|
||||
getentry (int entrycount, unsigned char dvdbuffer[])
|
||||
{
|
||||
@ -449,7 +445,7 @@ getentry (int entrycount, unsigned char dvdbuffer[])
|
||||
if(!newBrowserList) // failed to allocate required memory
|
||||
{
|
||||
ResetBrowser();
|
||||
ErrorPrompt("Out of memory: too many files!");
|
||||
WaitPrompt("Out of memory: too many files!");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
@ -459,16 +455,8 @@ getentry (int entrycount, unsigned char dvdbuffer[])
|
||||
memset(&(browserList[entrycount]), 0, sizeof(BROWSERENTRY)); // clear the new entry
|
||||
|
||||
strncpy (browserList[entrycount].filename, fname, MAXJOLIET);
|
||||
|
||||
if(strcmp(fname,"..") == 0)
|
||||
{
|
||||
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);
|
||||
|
||||
@ -495,7 +483,7 @@ getentry (int entrycount, unsigned char dvdbuffer[])
|
||||
* It relies on dvddir and dvddirlength being pre-populated by a call to
|
||||
* 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
|
||||
ParseDVDdirectory ()
|
||||
@ -518,7 +506,7 @@ ParseDVDdirectory ()
|
||||
while (len < pdlength)
|
||||
{
|
||||
if (dvd_read (&dvdbuffer, 2048, pdoffset) == 0)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
diroffset = 0;
|
||||
|
||||
@ -535,7 +523,6 @@ ParseDVDdirectory ()
|
||||
// Sort the file list
|
||||
qsort(browserList, filecount, sizeof(BROWSERENTRY), FileSortCallback);
|
||||
|
||||
browser.numEntries = filecount;
|
||||
return filecount;
|
||||
}
|
||||
|
||||
@ -543,6 +530,7 @@ ParseDVDdirectory ()
|
||||
* SetDVDdirectory
|
||||
* Set the current DVD file offset
|
||||
***************************************************************************/
|
||||
|
||||
void SetDVDdirectory(u64 dir, int length)
|
||||
{
|
||||
dvddir = dir;
|
||||
@ -591,18 +579,12 @@ static bool SwitchDVDFolderR(char * dir, int maxDepth)
|
||||
|
||||
if(dirindex >= 0)
|
||||
{
|
||||
dvddir = browserList[dirindex].offset;
|
||||
dvddirlength = browserList[dirindex].length;
|
||||
browser.selIndex = dirindex;
|
||||
|
||||
if(browserList[dirindex].isdir) // only parse directories
|
||||
{
|
||||
UpdateDirName(METHOD_DVD);
|
||||
ParseDVDdirectory();
|
||||
}
|
||||
else
|
||||
{
|
||||
dvddir = browserList[dirindex].offset;
|
||||
dvddirlength = browserList[dirindex].length;
|
||||
}
|
||||
browser.numEntries = ParseDVDdirectory();
|
||||
|
||||
if(lastdir)
|
||||
return true;
|
||||
@ -615,8 +597,8 @@ static bool SwitchDVDFolderR(char * dir, int maxDepth)
|
||||
bool SwitchDVDFolder(char origdir[])
|
||||
{
|
||||
// make a copy of origdir so we don't mess with original
|
||||
char dir[1024];
|
||||
strncpy(dir, origdir, 1024);
|
||||
char dir[200];
|
||||
strcpy(dir, origdir);
|
||||
|
||||
char * dirptr = dir;
|
||||
|
||||
@ -630,7 +612,6 @@ bool SwitchDVDFolder(char origdir[])
|
||||
// start searching at root of DVD
|
||||
dvddir = dvdrootdir;
|
||||
dvddirlength = dvdrootlength;
|
||||
browser.dir[0] = 0;
|
||||
ParseDVDdirectory();
|
||||
|
||||
return SwitchDVDFolderR(dirptr, 0);
|
||||
@ -641,10 +622,10 @@ bool SwitchDVDFolder(char origdir[])
|
||||
* This function will load a file from DVD
|
||||
* It assumes dvddir and dvddirlength are prepopulated
|
||||
***************************************************************************/
|
||||
|
||||
int
|
||||
LoadDVDFileOffset (unsigned char *buffer, int length)
|
||||
{
|
||||
int result = 0;
|
||||
int offset;
|
||||
int blocks;
|
||||
int i;
|
||||
@ -662,19 +643,17 @@ LoadDVDFileOffset (unsigned char *buffer, int length)
|
||||
{
|
||||
ret = dvd_read (buffer, length, discoffset);
|
||||
if(ret <= 0) // read failure
|
||||
goto done;
|
||||
else
|
||||
result = length;
|
||||
return 0;
|
||||
}
|
||||
else // load whole file
|
||||
{
|
||||
ret = dvd_read (readbuffer, 2048, discoffset);
|
||||
if(ret <= 0) // read failure
|
||||
goto done;
|
||||
return 0;
|
||||
|
||||
if (IsZipFile (readbuffer))
|
||||
{
|
||||
result = UnZipBuffer (buffer, METHOD_DVD); // unzip from dvd
|
||||
return UnZipBuffer (buffer, METHOD_DVD); // unzip from dvd
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -682,7 +661,7 @@ LoadDVDFileOffset (unsigned char *buffer, int length)
|
||||
{
|
||||
ret = dvd_read (readbuffer, 2048, discoffset);
|
||||
if(ret <= 0) // read failure
|
||||
goto done;
|
||||
return 0;
|
||||
memcpy (buffer + offset, readbuffer, 2048);
|
||||
offset += 2048;
|
||||
discoffset += 2048;
|
||||
@ -695,15 +674,12 @@ LoadDVDFileOffset (unsigned char *buffer, int length)
|
||||
i = dvddirlength % 2048;
|
||||
ret = dvd_read (readbuffer, 2048, discoffset);
|
||||
if(ret <= 0) // read failure
|
||||
goto done;
|
||||
return 0;
|
||||
memcpy (buffer + offset, readbuffer, i);
|
||||
}
|
||||
result = dvddirlength;
|
||||
}
|
||||
}
|
||||
done:
|
||||
CancelAction();
|
||||
return result;
|
||||
return dvddirlength;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -712,30 +688,20 @@ done:
|
||||
* It will attempt to find the offset of the file, and if successful it
|
||||
* will populate dvddir and dvddirlength, and load the file
|
||||
***************************************************************************/
|
||||
|
||||
int
|
||||
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))
|
||||
ret = LoadDVDFileOffset ((unsigned char *)buffer, datasize);
|
||||
else if(!silent)
|
||||
ErrorPrompt("Error loading file!");
|
||||
|
||||
// restore browser information
|
||||
memset(browser.dir, 0, MAXPATHLEN);
|
||||
strncpy(browser.dir, origDir, MAXPATHLEN);
|
||||
browser.selIndex = origSelIndex;
|
||||
browser.pageIndex = origPageIndex;
|
||||
|
||||
return ret;
|
||||
{
|
||||
return LoadDVDFileOffset ((unsigned char *)buffer, datasize);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!silent)
|
||||
WaitPrompt("Error loading file!");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -802,8 +768,8 @@ int dvd_driveid()
|
||||
dvd[6] = 0x20;
|
||||
dvd[7] = 3;
|
||||
|
||||
while( dvd[7] & 1 );
|
||||
|
||||
while( dvd[7] & 1 )
|
||||
;
|
||||
DCFlushRange((void *)0x80000000, 32);
|
||||
|
||||
return (int)inquiry[2];
|
||||
|
@ -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;
|
||||
}
|
@ -5,8 +5,7 @@
|
||||
*
|
||||
* filelist.h
|
||||
*
|
||||
* Contains a list of all of the files stored in the images/, fonts/, and
|
||||
* sounds/ folders
|
||||
* Contains a list of all of the files in the images/ folder
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _FILELIST_H_
|
||||
@ -17,208 +16,6 @@
|
||||
extern const u8 font_ttf[];
|
||||
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 u32 player1_point_png_size;
|
||||
|
||||
|
@ -29,8 +29,8 @@
|
||||
#include "memcardop.h"
|
||||
#include "gcunzip.h"
|
||||
#include "video.h"
|
||||
#include "menu.h"
|
||||
#include "filebrowser.h"
|
||||
#include "menudraw.h"
|
||||
#include "filesel.h"
|
||||
#include "preferences.h"
|
||||
|
||||
unsigned char * savebuffer = NULL;
|
||||
@ -49,7 +49,7 @@ bool isMounted[9] = { false, false, false, false, false, false, false, false, fa
|
||||
/****************************************************************************
|
||||
* deviceThreading
|
||||
***************************************************************************/
|
||||
lwp_t devicethread = LWP_THREAD_NULL;
|
||||
lwp_t devicethread;
|
||||
|
||||
/****************************************************************************
|
||||
* devicecallback
|
||||
@ -103,6 +103,7 @@ devicecallback (void *arg)
|
||||
#endif
|
||||
usleep(500000); // suspend thread for 1/2 sec
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -115,7 +116,7 @@ devicecallback (void *arg)
|
||||
void
|
||||
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;
|
||||
fatUnmount(rootdir);
|
||||
disc->shutdown();
|
||||
isMounted[method] = false;
|
||||
}
|
||||
if(!isMounted[method])
|
||||
{
|
||||
@ -227,7 +227,7 @@ bool ChangeInterface(int method, bool silent)
|
||||
mounted = MountFAT(METHOD_SD_SLOTB); // try SD Gecko on slot B
|
||||
#endif
|
||||
if(!mounted && !silent) // no SD device found
|
||||
ErrorPrompt("SD card not found!");
|
||||
WaitPrompt ("SD card not found!");
|
||||
}
|
||||
else if(method == METHOD_USB)
|
||||
{
|
||||
@ -235,31 +235,19 @@ bool ChangeInterface(int method, bool silent)
|
||||
mounted = MountFAT(method);
|
||||
|
||||
if(!mounted && !silent)
|
||||
ErrorPrompt("USB drive not found!");
|
||||
WaitPrompt ("USB drive not found!");
|
||||
#endif
|
||||
}
|
||||
else if(method == METHOD_DVD)
|
||||
{
|
||||
rootdir[0] = 0;
|
||||
sprintf(rootdir, "/");
|
||||
mounted = MountDVD(silent);
|
||||
}
|
||||
#ifdef HW_RVL
|
||||
else if(method == METHOD_SMB)
|
||||
{
|
||||
sprintf(rootdir, "smb:/");
|
||||
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;
|
||||
}
|
||||
@ -268,49 +256,39 @@ bool ChangeInterface(int method, bool silent)
|
||||
* Browse subdirectories
|
||||
**************************************************************************/
|
||||
int
|
||||
ParseDirectory(int method)
|
||||
ParseDirectory()
|
||||
{
|
||||
DIR_ITER *dir = NULL;
|
||||
DIR_ITER *dir;
|
||||
char fulldir[MAXPATHLEN];
|
||||
char filename[MAXPATHLEN];
|
||||
char tmpname[MAXPATHLEN];
|
||||
struct stat filestat;
|
||||
char msg[128];
|
||||
int retry = 1;
|
||||
bool mounted = false;
|
||||
|
||||
// reset browser
|
||||
ResetBrowser();
|
||||
|
||||
ShowAction("Loading...");
|
||||
// add device to path
|
||||
sprintf(fulldir, "%s%s", rootdir, browser.dir);
|
||||
|
||||
// open the directory
|
||||
while(dir == NULL && retry == 1)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
dir = diropen(fulldir);
|
||||
|
||||
// if we can't open the dir, try opening the root dir
|
||||
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(msg, "Error opening %s", rootdir);
|
||||
ErrorPrompt(msg);
|
||||
return -1;
|
||||
}
|
||||
WaitPrompt(msg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -326,8 +304,8 @@ ParseDirectory(int method)
|
||||
if(!newBrowserList) // failed to allocate required memory
|
||||
{
|
||||
ResetBrowser();
|
||||
ErrorPrompt("Out of memory: too many files!");
|
||||
entryNum = -1;
|
||||
WaitPrompt("Out of memory: too many files!");
|
||||
entryNum = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
@ -337,19 +315,9 @@ ParseDirectory(int method)
|
||||
memset(&(browserList[entryNum]), 0, sizeof(BROWSERENTRY)); // clear the new entry
|
||||
|
||||
strncpy(browserList[entryNum].filename, filename, MAXJOLIET);
|
||||
|
||||
if(strcmp(filename,"..") == 0)
|
||||
{
|
||||
sprintf(browserList[entryNum].displayname, "Up One Level");
|
||||
}
|
||||
else
|
||||
{
|
||||
ShortenFilename(tmpname, filename); // hide file extension
|
||||
StripExt(tmpname, filename); // hide file extension
|
||||
strncpy(browserList[entryNum].displayname, tmpname, MAXDISPLAY); // crop name for display
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
entryNum++;
|
||||
@ -362,9 +330,6 @@ ParseDirectory(int method)
|
||||
// Sort the file list
|
||||
qsort(browserList, entryNum, sizeof(BROWSERENTRY), FileSortCallback);
|
||||
|
||||
CancelAction();
|
||||
|
||||
browser.numEntries = entryNum;
|
||||
return entryNum;
|
||||
}
|
||||
|
||||
@ -375,8 +340,8 @@ ParseDirectory(int method)
|
||||
void
|
||||
AllocSaveBuffer ()
|
||||
{
|
||||
while(savebuffer != NULL) // save buffer is in use
|
||||
usleep(50); // wait for it to be free
|
||||
if (savebuffer != NULL)
|
||||
free(savebuffer);
|
||||
|
||||
savebuffer = (unsigned char *) memalign(32, SAVEBUFFERSIZE);
|
||||
memset (savebuffer, 0, SAVEBUFFERSIZE);
|
||||
@ -417,7 +382,7 @@ LoadSzFile(char * filepath, unsigned char * rbuffer)
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorPrompt("Error opening file");
|
||||
WaitPrompt("Error opening file");
|
||||
}
|
||||
|
||||
// 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];
|
||||
u32 size = 0;
|
||||
u32 readsize = 0;
|
||||
char fullpath[MAXPATHLEN];
|
||||
int retry = 1;
|
||||
|
||||
if(!ChangeInterface(method, NOTSILENT))
|
||||
return 0;
|
||||
|
||||
switch(method)
|
||||
{
|
||||
@ -455,12 +421,10 @@ LoadFile (char * rbuffer, char *filepath, u32 length, int method, bool silent)
|
||||
// since we're loading a file
|
||||
LWP_SuspendThread (devicethread);
|
||||
|
||||
// open the file
|
||||
while(!size && retry == 1)
|
||||
{
|
||||
if(ChangeInterface(method, silent))
|
||||
{
|
||||
sprintf(fullpath, "%s%s", rootdir, filepath); // add device to filepath
|
||||
// add device to filepath
|
||||
char fullpath[1024];
|
||||
sprintf(fullpath, "%s%s", rootdir, filepath);
|
||||
|
||||
file = fopen (fullpath, "rb");
|
||||
|
||||
if (file > 0)
|
||||
@ -488,21 +452,17 @@ LoadFile (char * rbuffer, char *filepath, u32 length, int method, bool silent)
|
||||
memcpy (rbuffer, zipbuffer, readsize); // copy what we already read
|
||||
|
||||
u32 offset = readsize;
|
||||
u32 nextread = 0;
|
||||
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
|
||||
readsize = fread (rbuffer + offset, 1, (1024*512), file); // read in 512K chunks
|
||||
|
||||
if(readsize <= 0 || readsize > nextread)
|
||||
if(readsize <= 0 || readsize > (1024*512))
|
||||
break; // read failure
|
||||
|
||||
if(readsize > 0)
|
||||
offset += readsize;
|
||||
}
|
||||
CancelAction();
|
||||
|
||||
if(offset != size) // # bytes read doesn't match # expected
|
||||
size = 0;
|
||||
@ -511,28 +471,19 @@ LoadFile (char * rbuffer, char *filepath, u32 length, int method, bool silent)
|
||||
}
|
||||
fclose (file);
|
||||
}
|
||||
}
|
||||
if(!size)
|
||||
{
|
||||
if(!silent)
|
||||
if(!size && !silent)
|
||||
{
|
||||
unmountRequired[method] = true;
|
||||
retry = ErrorPromptRetry("Error loading file!");
|
||||
}
|
||||
else
|
||||
{
|
||||
retry = 0;
|
||||
}
|
||||
}
|
||||
WaitPrompt("Error loading file!");
|
||||
}
|
||||
|
||||
// go back to checking if devices were inserted/removed
|
||||
LWP_ResumeThread (devicethread);
|
||||
CancelAction();
|
||||
|
||||
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);
|
||||
}
|
||||
@ -544,59 +495,53 @@ u32 LoadFile(char * filepath, int method, bool silent)
|
||||
u32
|
||||
SaveFile (char * buffer, char *filepath, u32 datasize, int method, bool silent)
|
||||
{
|
||||
char fullpath[MAXPATHLEN];
|
||||
u32 written = 0;
|
||||
int retry = 1;
|
||||
|
||||
if(datasize == 0)
|
||||
if(!ChangeInterface(method, NOTSILENT))
|
||||
return 0;
|
||||
|
||||
ShowAction("Saving...");
|
||||
|
||||
if(method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB)
|
||||
switch(method)
|
||||
{
|
||||
if(method == METHOD_MC_SLOTA)
|
||||
case METHOD_MC_SLOTA:
|
||||
return SaveMCFile (buffer, CARD_SLOTA, filepath, datasize, silent);
|
||||
else
|
||||
break;
|
||||
case METHOD_MC_SLOTB:
|
||||
return SaveMCFile (buffer, CARD_SLOTB, filepath, datasize, silent);
|
||||
break;
|
||||
}
|
||||
|
||||
if (datasize)
|
||||
{
|
||||
// stop checking if devices were removed/inserted
|
||||
// since we're saving a file
|
||||
LWP_SuspendThread (devicethread);
|
||||
|
||||
while(!written && retry == 1)
|
||||
{
|
||||
if(ChangeInterface(method, silent))
|
||||
{
|
||||
sprintf(fullpath, "%s%s", rootdir, filepath); // add device to filepath
|
||||
// add device to filepath
|
||||
char fullpath[1024];
|
||||
sprintf(fullpath, "%s%s", rootdir, filepath);
|
||||
|
||||
// open file for writing
|
||||
file = fopen (fullpath, "wb");
|
||||
|
||||
if (file > 0)
|
||||
{
|
||||
written = fwrite (savebuffer, 1, datasize, file);
|
||||
if(written < datasize) written = 0;
|
||||
fclose (file);
|
||||
}
|
||||
}
|
||||
if(!written)
|
||||
|
||||
if(!written && !silent)
|
||||
{
|
||||
unmountRequired[method] = true;
|
||||
if(!silent)
|
||||
retry = ErrorPromptRetry("Error saving file!");
|
||||
else
|
||||
retry = 0;
|
||||
}
|
||||
WaitPrompt ("Error saving file!");
|
||||
}
|
||||
|
||||
// go back to checking if devices were inserted/removed
|
||||
LWP_ResumeThread (devicethread);
|
||||
|
||||
CancelAction();
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
@ -24,14 +24,14 @@ void InitDeviceThread();
|
||||
void MountAllFAT();
|
||||
void UnmountAllFAT();
|
||||
bool ChangeInterface(int method, bool silent);
|
||||
int ParseDirectory(int method);
|
||||
int ParseDirectory();
|
||||
void AllocSaveBuffer();
|
||||
void FreeSaveBuffer();
|
||||
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 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 FILE * file;
|
||||
|
582
source/ngc/filesel.cpp
Normal 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;
|
||||
}
|
@ -3,19 +3,18 @@
|
||||
*
|
||||
* Tantric September 2008
|
||||
*
|
||||
* filebrowser.h
|
||||
* filesel.h
|
||||
*
|
||||
* Generic file routines - reading, writing, browsing
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _FILEBROWSER_H_
|
||||
#define _FILEBROWSER_H_
|
||||
#ifndef _NGCFILESEL_
|
||||
#define _NGCFILESEL_
|
||||
|
||||
#include <unistd.h>
|
||||
#include <gccore.h>
|
||||
|
||||
#define MAXJOLIET 255
|
||||
#define MAXDISPLAY 35
|
||||
#define MAXDISPLAY 40
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -29,7 +28,6 @@ typedef struct
|
||||
{
|
||||
u64 offset; // DVD offset
|
||||
unsigned int length; // file length
|
||||
time_t mtime; // file modified time
|
||||
char isdir; // 0 - file, 1 - directory
|
||||
char filename[MAXJOLIET + 1]; // full filename
|
||||
char displayname[MAXDISPLAY + 1]; // name for browser display
|
||||
@ -38,23 +36,17 @@ typedef struct
|
||||
extern BROWSERINFO browser;
|
||||
extern BROWSERENTRY * browserList;
|
||||
extern char rootdir[10];
|
||||
extern char ROMFilename[512];
|
||||
extern bool ROMLoaded;
|
||||
extern char szpath[MAXPATHLEN];
|
||||
extern bool inSz;
|
||||
extern char ROMFilename[512];
|
||||
|
||||
bool MakeFilePath(char filepath[], int type, int method, char * filename = NULL, int filenum = -2);
|
||||
int UpdateDirName(int method);
|
||||
int OpenGameList();
|
||||
bool MakeFilePath(char filepath[], int type, int method);
|
||||
int OpenROM (int method);
|
||||
int autoLoadMethod();
|
||||
int autoSaveMethod(bool silent);
|
||||
int FileSortCallback(const void *f1, const void *f2);
|
||||
void StripExt(char* returnstring, char * inputstring);
|
||||
void ShortenFilename(char* returnstring, char * inputstring);
|
||||
bool IsSz();
|
||||
void ResetBrowser();
|
||||
int BrowserLoadSz(int method);
|
||||
int BrowserChangeFolder(int method);
|
||||
int BrowserLoadFile(int method);
|
||||
|
||||
|
||||
#endif
|
@ -30,17 +30,234 @@
|
||||
#include "gba/bios.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_start( args, format );
|
||||
vsprintf( DebugStr, format, 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 J = StandardMovement(pad) | DecodeGamecube(pad) | DPadWASD(pad);
|
||||
u32 J = StandardMovement(pad) | DecodeGamecube(pad) | DecodeKeyboard(pad);
|
||||
// Rumble when they lose health!
|
||||
u8 Health = 0;
|
||||
static u8 OldHealth = 0;
|
||||
@ -49,14 +266,6 @@ u32 LegoStarWars1Input(unsigned short pad) {
|
||||
OldHealth = Health;
|
||||
|
||||
#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);
|
||||
|
||||
// Start/Select
|
||||
@ -95,7 +304,7 @@ u32 LegoStarWars1Input(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!
|
||||
u8 Health = 0;
|
||||
static u8 OldHealth = 0;
|
||||
@ -104,14 +313,6 @@ u32 LegoStarWars2Input(unsigned short pad) {
|
||||
OldHealth = Health;
|
||||
|
||||
#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);
|
||||
|
||||
// Start/Select
|
||||
|
@ -20,14 +20,13 @@ extern "C" {
|
||||
#include "../sz/7zExtract.h"
|
||||
}
|
||||
|
||||
#include "vba.h"
|
||||
#include "dvd.h"
|
||||
#include "networkop.h"
|
||||
#include "fileop.h"
|
||||
#include "filebrowser.h"
|
||||
#include "video.h"
|
||||
#include "menu.h"
|
||||
#include "menudraw.h"
|
||||
#include "gcunzip.h"
|
||||
#include "vba.h"
|
||||
|
||||
#define ZIPCHUNK 2048
|
||||
|
||||
@ -147,7 +146,7 @@ UnZipBuffer (unsigned char *outbuffer, int method)
|
||||
res = inflateInit2 (&zs, -MAX_WBITS);
|
||||
|
||||
if (res != Z_OK)
|
||||
goto done;
|
||||
return 0;
|
||||
|
||||
/*** Set ZipChunk for first pass ***/
|
||||
zipoffset =
|
||||
@ -171,7 +170,8 @@ UnZipBuffer (unsigned char *outbuffer, int method)
|
||||
|
||||
if (res == Z_MEM_ERROR)
|
||||
{
|
||||
goto done;
|
||||
inflateEnd (&zs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
have = ZIPCHUNK - zs.avail_out;
|
||||
@ -199,19 +199,22 @@ UnZipBuffer (unsigned char *outbuffer, int method)
|
||||
break;
|
||||
}
|
||||
if(sizeread <= 0)
|
||||
goto done; // read failure
|
||||
break; // read failure
|
||||
|
||||
ShowProgress ("Loading...", bufferoffset, pkzip.uncompressedSize);
|
||||
}
|
||||
while (res != Z_STREAM_END);
|
||||
|
||||
done:
|
||||
inflateEnd (&zs);
|
||||
CancelAction();
|
||||
|
||||
if (res == Z_STREAM_END)
|
||||
return pkzip.uncompressedSize;
|
||||
{
|
||||
if (pkzip.uncompressedSize == (u32) bufferoffset)
|
||||
return bufferoffset;
|
||||
else
|
||||
return pkzip.uncompressedSize;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -245,7 +248,7 @@ GetFirstZipFilename (int method)
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorPrompt("Error - Invalid ZIP file!");
|
||||
WaitPrompt("Error - Invalid ZIP file!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -315,7 +318,7 @@ Is7ZipFile (char *buffer)
|
||||
// display an error message
|
||||
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
|
||||
@ -470,7 +473,7 @@ int SzParse(char * filepath, int method)
|
||||
if(!newBrowserList) // failed to allocate required memory
|
||||
{
|
||||
ResetBrowser();
|
||||
ErrorPrompt("Out of memory: too many files!");
|
||||
WaitPrompt("Out of memory: too many files!");
|
||||
nbfiles = 0;
|
||||
break;
|
||||
}
|
||||
@ -482,9 +485,7 @@ int SzParse(char * filepath, int method)
|
||||
|
||||
// parse information about this file to the dvd file list structure
|
||||
strncpy(browserList[SzJ].filename, SzF->Name, MAXJOLIET); // copy joliet name (useless...)
|
||||
char tmpname[MAXJOLIET+1] = "";
|
||||
ShortenFilename(tmpname, browserList[SzJ].filename);
|
||||
strncpy(browserList[SzJ].displayname, tmpname, MAXDISPLAY); // crop name for display
|
||||
strncpy(browserList[SzJ].displayname, SzF->Name, MAXDISPLAY); // crop name for display
|
||||
browserList[SzJ].length = SzF->Size; // filesize
|
||||
browserList[SzJ].offset = SzI; // the extraction function identifies the file with this number
|
||||
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
|
||||
SzClose();
|
||||
|
||||
CancelAction();
|
||||
|
||||
// check for errors
|
||||
if(SzRes != SZ_OK)
|
||||
{
|
||||
|
@ -1,35 +1,15 @@
|
||||
/*!\mainpage libwiigui Documentation
|
||||
/****************************************************************************
|
||||
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||
*
|
||||
* \section Introduction
|
||||
* 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!
|
||||
* Tantric February 2009
|
||||
*
|
||||
* \section Quickstart
|
||||
* 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.h
|
||||
*
|
||||
*/
|
||||
* GUI class definitions
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef LIBWIIGUI_H
|
||||
#define LIBWIIGUI_H
|
||||
#ifndef GUI_H
|
||||
#define GUI_H
|
||||
|
||||
#include <gccore.h>
|
||||
#include <malloc.h>
|
||||
@ -37,25 +17,38 @@
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include <math.h>
|
||||
#include <asndlib.h>
|
||||
#include <wiiuse/wpad.h>
|
||||
#include <mp3player.h>
|
||||
#include "pngu/pngu.h"
|
||||
#include "FreeTypeGX.h"
|
||||
#include "vba.h"
|
||||
#include "video.h"
|
||||
#include "input.h"
|
||||
#include "filelist.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_LOOP_DELAY 3
|
||||
#define PAGESIZE 8
|
||||
|
||||
#define SAVELISTSIZE 6
|
||||
#define MAX_SAVES 20
|
||||
#define MAX_OPTIONS 30
|
||||
|
||||
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
|
||||
{
|
||||
ALIGN_LEFT,
|
||||
@ -76,15 +69,9 @@ enum
|
||||
|
||||
enum
|
||||
{
|
||||
SOUND_PCM,
|
||||
SOUND_OGG
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
IMAGE_TEXTURE,
|
||||
IMAGE_COLOR,
|
||||
IMAGE_DATA
|
||||
TRIGGER_SIMPLE,
|
||||
TRIGGER_BUTTON_ONLY,
|
||||
TRIGGER_BUTTON_ONLY_IN_FOCUS
|
||||
};
|
||||
|
||||
#define EFFECT_SLIDE_TOP 1
|
||||
@ -97,696 +84,146 @@ enum
|
||||
#define EFFECT_SCALE 128
|
||||
#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
|
||||
{
|
||||
public:
|
||||
//!Constructor
|
||||
//!\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(const u8 * s, int l);
|
||||
~GuiSound();
|
||||
//!Start sound playback
|
||||
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:
|
||||
const u8 * sound; //!< Pointer to the sound data
|
||||
int type; //!< Sound format type (SOUND_PCM or SOUND_OGG)
|
||||
s32 length; //!< Length of sound data
|
||||
s32 voice; //!< Currently assigned ASND voice channel
|
||||
s32 volume; //!< Sound volume (0-100)
|
||||
bool loop; //!< Loop sound playback
|
||||
const u8 * sound;
|
||||
s32 length;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
//!Primary Gui class
|
||||
class GuiElement
|
||||
{
|
||||
public:
|
||||
//!Constructor
|
||||
GuiElement();
|
||||
//!Destructor
|
||||
~GuiElement();
|
||||
//!Set the element's parent
|
||||
//!\param e Pointer to parent element
|
||||
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();
|
||||
//!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();
|
||||
//!Gets the current width of the element. Does not currently consider the scale
|
||||
//!\return width
|
||||
int GetWidth();
|
||||
//!Gets the height of the element. Does not currently consider the scale
|
||||
//!\return height
|
||||
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);
|
||||
//!Checks whether or not the element is visible
|
||||
//!\return true if visible, false otherwise
|
||||
bool IsVisible();
|
||||
//!Checks whether or not the element is selectable
|
||||
//!\return true if selectable, false otherwise
|
||||
bool IsSelectable();
|
||||
//!Checks whether or not the element is clickable
|
||||
//!\return true if clickable, false otherwise
|
||||
bool IsClickable();
|
||||
//!Sets whether or not the element is selectable
|
||||
//!\param s Selectable
|
||||
void SetSelectable(bool s);
|
||||
//!Sets whether or not the element is clickable
|
||||
//!\param c Clickable
|
||||
void SetClickable(bool c);
|
||||
//!Gets the element's current state
|
||||
//!\return state
|
||||
int GetState();
|
||||
//!Sets the element's alpha value
|
||||
//!\param a alpha value
|
||||
void SetVisible(bool v);
|
||||
void SetAlpha(int a);
|
||||
//!Gets the element's alpha value
|
||||
//!Considers alpha, alphaDyn, and the parent element's GetAlpha() value
|
||||
//!\return alpha
|
||||
int GetAlpha();
|
||||
//!Sets the element's scale
|
||||
//!\param s scale (1 is 100%)
|
||||
void SetScale(float s);
|
||||
//!Gets the element's current scale
|
||||
//!Considers scale, scaleDyn, and the parent element's GetScale() value
|
||||
float GetScale();
|
||||
//!Set a new GuiTrigger for the element
|
||||
//!\param t Pointer to GuiTrigger
|
||||
void SetTrigger(GuiTrigger * t);
|
||||
//!\overload
|
||||
//!\param i Index of trigger array to set
|
||||
//!\param t Pointer to GuiTrigger
|
||||
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);
|
||||
//!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);
|
||||
//!Shortcut to SetEffectOnOver(EFFECT_SCALE, 4, 110)
|
||||
void SetEffectGrow();
|
||||
//!Gets the current element effects
|
||||
//!\return element effects
|
||||
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);
|
||||
//!Sets the element's position
|
||||
//!\param x X coordinate
|
||||
//!\param y Y coordinate
|
||||
void SetPosition(int x, int y);
|
||||
//!Updates the element's effects (dynamic values)
|
||||
//!Called by Draw(), used for animation purposes
|
||||
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);
|
||||
//!Checks whether the element is in focus
|
||||
//!\return true if element is in focus, false otherwise
|
||||
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);
|
||||
//!Sets the element's state
|
||||
//!\param v State (STATE_DEFAULT, STATE_SELECTED, STATE_CLICKED, STATE_DISABLED)
|
||||
virtual void SetState(int s);
|
||||
//!Resets the element's state to STATE_DEFAULT
|
||||
virtual void ResetState();
|
||||
//!Gets whether or not the element is in STATE_SELECTED
|
||||
//!\return true if selected, false otherwise
|
||||
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);
|
||||
//!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);
|
||||
//!Called constantly to redraw the element
|
||||
virtual void Draw();
|
||||
protected:
|
||||
bool visible; //!< Visibility of the element. If false, Draw() is skipped
|
||||
int focus; //!< Element focus (-1 = focus disabled, 0 = not focused, 1 = focused)
|
||||
int width; //!< Element width
|
||||
int height; //!< Element height
|
||||
int xoffset; //!< Element X offset
|
||||
int yoffset; //!< Element Y offset
|
||||
int xoffsetDyn; //!< Element X offset, dynamic (added to xoffset value for animation effects)
|
||||
int yoffsetDyn; //!< Element Y offset, dynamic (added to yoffset value for animation effects)
|
||||
int alpha; //!< Element alpha value (0-255)
|
||||
f32 scale; //!< Element scale (1 = 100%)
|
||||
int alphaDyn; //!< Element alpha, dynamic (multiplied by alpha value for blending/fading effects)
|
||||
f32 scaleDyn; //!< Element scale, dynamic (multiplied by alpha value for blending/fading effects)
|
||||
bool rumble; //!< Wiimote rumble (on/off) - set to on when this element requests a rumble event
|
||||
int effects; //!< Currently enabled effect(s). 0 when no effects are enabled
|
||||
int effectAmount; //!< Effect amount. Used by different effects for different purposes
|
||||
int effectTarget; //!< Effect target amount. Used by different effects for different purposes
|
||||
int effectsOver; //!< Effects to enable when wiimote cursor is over this element. Copied to effects variable on over event
|
||||
int effectAmountOver; //!< EffectAmount to set when wiimote cursor is over this element
|
||||
int effectTargetOver; //!< EffectTarget to set when wiimote cursor is over this element
|
||||
int alignmentHor; //!< Horizontal element alignment, respective to parent element (LEFT, RIGHT, CENTRE)
|
||||
int alignmentVert; //!< Horizontal element alignment, respective to parent element (TOP, BOTTOM, MIDDLE)
|
||||
int state; //!< Element state (DEFAULT, SELECTED, CLICKED, DISABLED)
|
||||
bool selectable; //!< Whether or not this element selectable (can change to SELECTED state)
|
||||
bool clickable; //!< Whether or not this element is clickable (can change to CLICKED state)
|
||||
GuiTrigger * trigger[2]; //!< GuiTriggers (input actions) that this element responds to
|
||||
GuiElement * parentElement; //!< Parent element
|
||||
UpdateCallback updateCB; //!< Callback function to call when this element is updated
|
||||
bool visible;
|
||||
int focus; // -1 = cannot focus, 0 = not focused, 1 = focused
|
||||
int width;
|
||||
int height;
|
||||
int xoffset;
|
||||
int yoffset;
|
||||
int xoffsetDyn;
|
||||
int yoffsetDyn;
|
||||
int alpha;
|
||||
f32 scale;
|
||||
int alphaDyn;
|
||||
f32 scaleDyn;
|
||||
int effects;
|
||||
int effectAmount;
|
||||
int effectTarget;
|
||||
int effectsOver;
|
||||
int effectAmountOver;
|
||||
int effectTargetOver;
|
||||
int alignmentHor; // LEFT, RIGHT, CENTRE
|
||||
int alignmentVert; // TOP, BOTTOM, MIDDLE
|
||||
int state; // DEFAULT, SELECTED, CLICKED, DISABLED
|
||||
bool selectable; // is SELECTED a valid state?
|
||||
bool clickable; // is CLICKED a valid state?
|
||||
GuiTrigger * trigger[2];
|
||||
GuiElement * parentElement;
|
||||
UpdateCallback updateCB;
|
||||
};
|
||||
|
||||
//!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
|
||||
{
|
||||
public:
|
||||
//!Constructor
|
||||
//!Converts the image data to RGBA8 - expects PNG format
|
||||
//!\param i Image data
|
||||
GuiImageData(const u8 * i);
|
||||
//!Destructor
|
||||
~GuiImageData();
|
||||
//!Gets a pointer to the image data
|
||||
//!\return pointer to image data
|
||||
u8 * GetImage();
|
||||
//!Gets the image width
|
||||
//!\return image width
|
||||
int GetWidth();
|
||||
//!Gets the image height
|
||||
//!\return image height
|
||||
int GetHeight();
|
||||
protected:
|
||||
u8 * data; //!< Image data
|
||||
int height; //!< Height of image
|
||||
int width; //!< Width of image
|
||||
u8 * data;
|
||||
int height;
|
||||
int width;
|
||||
};
|
||||
|
||||
//!Display, manage, and manipulate images in the Gui
|
||||
class GuiImage : public GuiElement
|
||||
{
|
||||
public:
|
||||
//!Constructor
|
||||
//!\param img Pointer to GuiImageData element
|
||||
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);
|
||||
//!\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);
|
||||
//!Destructor
|
||||
~GuiImage();
|
||||
//!Sets the image rotation angle for drawing
|
||||
//!\param a Angle (in degrees)
|
||||
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);
|
||||
//!Constantly called to draw the image
|
||||
void Draw();
|
||||
//!Gets the image data
|
||||
//!\return pointer to image data
|
||||
u8 * GetImage();
|
||||
//!Sets up a new image using the GuiImageData object specified
|
||||
//!\param img Pointer to GuiImageData object
|
||||
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);
|
||||
//!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);
|
||||
//!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);
|
||||
//!Directly modifies the image data to create a color-striped effect
|
||||
//!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);
|
||||
void Stripe(int s);
|
||||
protected:
|
||||
int imgType; //!< Type of image data (IMAGE_TEXTURE, IMAGE_COLOR, IMAGE_DATA)
|
||||
u8 * image; //!< Poiner to image data. May be shared with GuiImageData data
|
||||
f32 imageangle; //!< Angle to draw the image
|
||||
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;
|
||||
u8 * image;
|
||||
f32 imageangle;
|
||||
int tile;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -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);
|
||||
}
|
@ -25,7 +25,6 @@ GuiElement::GuiElement()
|
||||
trigger[0] = NULL;
|
||||
trigger[1] = NULL;
|
||||
parentElement = NULL;
|
||||
rumble = true;
|
||||
selectable = false;
|
||||
clickable = false;
|
||||
visible = true;
|
||||
@ -284,16 +283,6 @@ void GuiElement::SetTrigger(u8 i, GuiTrigger * t)
|
||||
trigger[i] = t;
|
||||
}
|
||||
|
||||
bool GuiElement::Rumble()
|
||||
{
|
||||
return rumble;
|
||||
}
|
||||
|
||||
void GuiElement::SetRumble(bool r)
|
||||
{
|
||||
rumble = r;
|
||||
}
|
||||
|
||||
int GuiElement::GetEffect()
|
||||
{
|
||||
return effects;
|
||||
|
@ -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);
|
||||
}
|
@ -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();
|
||||
}
|
@ -14,45 +14,26 @@
|
||||
* Constructor for the GuiImageData class.
|
||||
*/
|
||||
GuiImageData::GuiImageData(const u8 * img)
|
||||
{
|
||||
if(img == NULL)
|
||||
{
|
||||
data = NULL;
|
||||
width = 0;
|
||||
height = 0;
|
||||
|
||||
if(img)
|
||||
{
|
||||
PNGUPROP imgProp;
|
||||
IMGCTX ctx = PNGU_SelectImageFromBuffer(img);
|
||||
|
||||
if(!ctx)
|
||||
return;
|
||||
|
||||
int res = PNGU_GetImageProperties(ctx, &imgProp);
|
||||
|
||||
if(res == PNGU_OK)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
PNGUPROP imgProp;
|
||||
IMGCTX ctx;
|
||||
|
||||
ctx = PNGU_SelectImageFromBuffer(img);
|
||||
PNGU_GetImageProperties (ctx, &imgProp);
|
||||
width = imgProp.imgWidth;
|
||||
height = imgProp.imgHeight;
|
||||
data = (u8 *)memalign (32, imgProp.imgWidth * imgProp.imgHeight * 4);
|
||||
PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, data, 255);
|
||||
PNGU_ReleaseImageContext (ctx);
|
||||
DCFlushRange (data, imgProp.imgWidth * imgProp.imgHeight * 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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();
|
||||
}
|
@ -75,8 +75,6 @@ void GuiTrigger::SetButtonOnlyInFocusTrigger(s32 ch, u32 wiibtns, u16 gcbtns)
|
||||
|
||||
s8 GuiTrigger::WPAD_Stick(u8 right, int axis)
|
||||
{
|
||||
#ifdef HW_RVL
|
||||
|
||||
float mag = 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);
|
||||
|
||||
return (s8)(val * 128.0f);
|
||||
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GuiTrigger::Left()
|
||||
@ -130,7 +124,7 @@ bool GuiTrigger::Left()
|
||||
u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_UP : WPAD_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
|
||||
|| WPAD_Stick(0,0) < -PADCAL)
|
||||
{
|
||||
@ -158,7 +152,7 @@ bool GuiTrigger::Right()
|
||||
u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_DOWN : WPAD_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
|
||||
|| WPAD_Stick(0,0) > PADCAL)
|
||||
{
|
||||
@ -186,7 +180,7 @@ bool GuiTrigger::Up()
|
||||
u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_RIGHT : WPAD_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
|
||||
|| WPAD_Stick(0,1) > PADCAL)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
@ -13,14 +13,16 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ogcsys.h>
|
||||
#include <network.h>
|
||||
#include <ogc/lwp_watchdog.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "menu.h"
|
||||
#include "menudraw.h"
|
||||
#include "http.h"
|
||||
|
||||
static s32 tcp_socket(void)
|
||||
@ -414,7 +416,6 @@ bool http_request(const char *url, FILE * hfile, u8 * buffer,
|
||||
ShowProgress("Downloading...", (content_length - bytesLeft),
|
||||
content_length);
|
||||
}
|
||||
CancelAction();
|
||||
}
|
||||
|
||||
if (!b || !res)
|
||||
|
Before Width: | Height: | Size: 216 B |
Before Width: | Height: | Size: 145 B |
Before Width: | Height: | Size: 230 B |
19212
source/ngc/images/bg.h
Normal file
Before Width: | Height: | Size: 843 B |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 279 B |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 299 B |
Before Width: | Height: | Size: 768 B |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 792 B |
Before Width: | Height: | Size: 764 B |
Before Width: | Height: | Size: 842 B |
Before Width: | Height: | Size: 776 B |
Before Width: | Height: | Size: 821 B |
Before Width: | Height: | Size: 775 B |
Before Width: | Height: | Size: 746 B |
Before Width: | Height: | Size: 710 B |
Before Width: | Height: | Size: 549 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 546 B |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 294 B |
Before Width: | Height: | Size: 434 B |
Before Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 524 B |
Before Width: | Height: | Size: 537 B |
Before Width: | Height: | Size: 632 B |
Before Width: | Height: | Size: 666 B |
Before Width: | Height: | Size: 582 B |
Before Width: | Height: | Size: 599 B |
Before Width: | Height: | Size: 714 B |
Before Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 160 B |
Before Width: | Height: | Size: 279 B |
Before Width: | Height: | Size: 777 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 270 B |
Before Width: | Height: | Size: 721 B |
Before Width: | Height: | Size: 733 B |
Before Width: | Height: | Size: 700 B |
Before Width: | Height: | Size: 739 B |
Before Width: | Height: | Size: 481 B |
Before Width: | Height: | Size: 469 B |
Before Width: | Height: | Size: 2.5 KiB |
@ -25,29 +25,26 @@
|
||||
#include "gameinput.h"
|
||||
#include "vbasupport.h"
|
||||
#include "wiiusbsupport.h"
|
||||
#include "gui/gui.h"
|
||||
#include "gba/GBA.h"
|
||||
#include "gba/bios.h"
|
||||
#include "gba/GBAinline.h"
|
||||
|
||||
extern bool InMenu;
|
||||
int rumbleRequest[4] = {0,0,0,0};
|
||||
GuiTrigger userInput[4];
|
||||
|
||||
#ifdef HW_RVL
|
||||
static int rumbleCount[4] = {0,0,0,0};
|
||||
#endif
|
||||
|
||||
bool cartridgeRumble = false;
|
||||
int gameRumbleCount = 0, menuRumbleCount = 0, rumbleCountAlready = 0;
|
||||
|
||||
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()
|
||||
{
|
||||
memset(btnmap, 0, sizeof(btnmap));
|
||||
|
||||
int i;
|
||||
int i = 0;
|
||||
|
||||
// VBA controller buttons
|
||||
// All other pads are mapped to this
|
||||
@ -65,72 +62,70 @@ void ResetControls()
|
||||
|
||||
/*** Gamecube controller Padmap ***/
|
||||
i=0;
|
||||
btnmap[CTRLR_GCPAD][i++] = PAD_BUTTON_B;
|
||||
btnmap[CTRLR_GCPAD][i++] = PAD_BUTTON_A;
|
||||
btnmap[CTRLR_GCPAD][i++] = PAD_TRIGGER_Z;
|
||||
btnmap[CTRLR_GCPAD][i++] = PAD_BUTTON_START;
|
||||
btnmap[CTRLR_GCPAD][i++] = PAD_BUTTON_UP;
|
||||
btnmap[CTRLR_GCPAD][i++] = PAD_BUTTON_DOWN;
|
||||
btnmap[CTRLR_GCPAD][i++] = PAD_BUTTON_LEFT;
|
||||
btnmap[CTRLR_GCPAD][i++] = PAD_BUTTON_RIGHT;
|
||||
btnmap[CTRLR_GCPAD][i++] = PAD_TRIGGER_L;
|
||||
btnmap[CTRLR_GCPAD][i++] = PAD_TRIGGER_R;
|
||||
gcpadmap[i++] = PAD_BUTTON_B;
|
||||
gcpadmap[i++] = PAD_BUTTON_A;
|
||||
gcpadmap[i++] = PAD_TRIGGER_Z;
|
||||
gcpadmap[i++] = PAD_BUTTON_START;
|
||||
gcpadmap[i++] = PAD_BUTTON_UP;
|
||||
gcpadmap[i++] = PAD_BUTTON_DOWN;
|
||||
gcpadmap[i++] = PAD_BUTTON_LEFT;
|
||||
gcpadmap[i++] = PAD_BUTTON_RIGHT;
|
||||
gcpadmap[i++] = PAD_TRIGGER_L;
|
||||
gcpadmap[i++] = PAD_TRIGGER_R;
|
||||
|
||||
/*** Wiimote Padmap ***/
|
||||
i=0;
|
||||
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_1;
|
||||
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_2;
|
||||
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_MINUS;
|
||||
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_PLUS;
|
||||
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_RIGHT;
|
||||
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_LEFT;
|
||||
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_UP;
|
||||
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_DOWN;
|
||||
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_B;
|
||||
btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_A;
|
||||
wmpadmap[i++] = WPAD_BUTTON_1;
|
||||
wmpadmap[i++] = WPAD_BUTTON_2;
|
||||
wmpadmap[i++] = WPAD_BUTTON_MINUS;
|
||||
wmpadmap[i++] = WPAD_BUTTON_PLUS;
|
||||
wmpadmap[i++] = WPAD_BUTTON_RIGHT;
|
||||
wmpadmap[i++] = WPAD_BUTTON_LEFT;
|
||||
wmpadmap[i++] = WPAD_BUTTON_UP;
|
||||
wmpadmap[i++] = WPAD_BUTTON_DOWN;
|
||||
wmpadmap[i++] = WPAD_BUTTON_B;
|
||||
wmpadmap[i++] = WPAD_BUTTON_A;
|
||||
|
||||
/*** Classic Controller Padmap ***/
|
||||
i=0;
|
||||
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_Y;
|
||||
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_B;
|
||||
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_MINUS;
|
||||
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_PLUS;
|
||||
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_UP;
|
||||
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_DOWN;
|
||||
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_LEFT;
|
||||
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_RIGHT;
|
||||
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_FULL_L;
|
||||
btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_FULL_R;
|
||||
ccpadmap[i++] = WPAD_CLASSIC_BUTTON_Y;
|
||||
ccpadmap[i++] = WPAD_CLASSIC_BUTTON_B;
|
||||
ccpadmap[i++] = WPAD_CLASSIC_BUTTON_MINUS;
|
||||
ccpadmap[i++] = WPAD_CLASSIC_BUTTON_PLUS;
|
||||
ccpadmap[i++] = WPAD_CLASSIC_BUTTON_UP;
|
||||
ccpadmap[i++] = WPAD_CLASSIC_BUTTON_DOWN;
|
||||
ccpadmap[i++] = WPAD_CLASSIC_BUTTON_LEFT;
|
||||
ccpadmap[i++] = WPAD_CLASSIC_BUTTON_RIGHT;
|
||||
ccpadmap[i++] = WPAD_CLASSIC_BUTTON_FULL_L;
|
||||
ccpadmap[i++] = WPAD_CLASSIC_BUTTON_FULL_R;
|
||||
|
||||
/*** Nunchuk + wiimote Padmap ***/
|
||||
i=0;
|
||||
btnmap[CTRLR_NUNCHUK][i++] = WPAD_NUNCHUK_BUTTON_C;
|
||||
btnmap[CTRLR_NUNCHUK][i++] = WPAD_NUNCHUK_BUTTON_Z;
|
||||
btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_MINUS;
|
||||
btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_PLUS;
|
||||
btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_UP;
|
||||
btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_DOWN;
|
||||
btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_LEFT;
|
||||
btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_RIGHT;
|
||||
btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_2;
|
||||
btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_1;
|
||||
ncpadmap[i++] = WPAD_NUNCHUK_BUTTON_C;
|
||||
ncpadmap[i++] = WPAD_NUNCHUK_BUTTON_Z;
|
||||
ncpadmap[i++] = WPAD_BUTTON_MINUS;
|
||||
ncpadmap[i++] = WPAD_BUTTON_PLUS;
|
||||
ncpadmap[i++] = WPAD_BUTTON_UP;
|
||||
ncpadmap[i++] = WPAD_BUTTON_DOWN;
|
||||
ncpadmap[i++] = WPAD_BUTTON_LEFT;
|
||||
ncpadmap[i++] = WPAD_BUTTON_RIGHT;
|
||||
ncpadmap[i++] = WPAD_BUTTON_2;
|
||||
ncpadmap[i++] = WPAD_BUTTON_1;
|
||||
|
||||
/*** Keyboard map ***/
|
||||
i=0;
|
||||
btnmap[CTRLR_KEYBOARD][i++] = KB_X; // VBA stupidly has B on the right instead of left
|
||||
btnmap[CTRLR_KEYBOARD][i++] = KB_Z;
|
||||
btnmap[CTRLR_KEYBOARD][i++] = KB_BKSP;
|
||||
btnmap[CTRLR_KEYBOARD][i++] = KB_ENTER;
|
||||
btnmap[CTRLR_KEYBOARD][i++] = KB_UP;
|
||||
btnmap[CTRLR_KEYBOARD][i++] = KB_DOWN;
|
||||
btnmap[CTRLR_KEYBOARD][i++] = KB_LEFT;
|
||||
btnmap[CTRLR_KEYBOARD][i++] = KB_RIGHT;
|
||||
btnmap[CTRLR_KEYBOARD][i++] = KB_A;
|
||||
btnmap[CTRLR_KEYBOARD][i++] = KB_S;
|
||||
kbpadmap[i++] = KB_X; // VBA stupidly has B on the right instead of left
|
||||
kbpadmap[i++] = KB_Z;
|
||||
kbpadmap[i++] = KB_BKSP;
|
||||
kbpadmap[i++] = KB_ENTER;
|
||||
kbpadmap[i++] = KB_UP;
|
||||
kbpadmap[i++] = KB_DOWN;
|
||||
kbpadmap[i++] = KB_LEFT;
|
||||
kbpadmap[i++] = KB_RIGHT;
|
||||
kbpadmap[i++] = KB_A;
|
||||
kbpadmap[i++] = KB_S;
|
||||
}
|
||||
|
||||
#ifdef HW_RVL
|
||||
|
||||
/****************************************************************************
|
||||
* ShutoffRumble
|
||||
***************************************************************************/
|
||||
@ -141,10 +136,8 @@ void ShutoffRumble()
|
||||
for(int i=0;i<4;i++)
|
||||
{
|
||||
WPAD_Rumble(i, 0);
|
||||
rumbleCount[i] = 0;
|
||||
}
|
||||
#endif
|
||||
PAD_ControlMotor(PAD_CHAN0, PAD_MOTOR_STOP);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -170,12 +163,10 @@ void DoRumble(int i)
|
||||
WPAD_Rumble(i, 0); // rumble off
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void updateRumble()
|
||||
{
|
||||
static void updateRumble() {
|
||||
bool r = false;
|
||||
if (ConfigRequested) r = (menuRumbleCount > 0);
|
||||
if (InMenu) r = (menuRumbleCount > 0);
|
||||
else r = cartridgeRumble || (gameRumbleCount > 0) || (menuRumbleCount > 0);
|
||||
|
||||
#ifdef HW_RVL
|
||||
@ -195,7 +186,7 @@ void updateRumbleFrame() {
|
||||
if (rumbleCountAlready > 50+10)
|
||||
rumbleCountAlready = 0;
|
||||
else rumbleCountAlready++;
|
||||
} else if (ConfigRequested) {
|
||||
} else if (InMenu) {
|
||||
if (menuRumbleCount>0)
|
||||
rumbleCountAlready++;
|
||||
} else {
|
||||
@ -203,7 +194,7 @@ void updateRumbleFrame() {
|
||||
rumbleCountAlready++;
|
||||
}
|
||||
updateRumble();
|
||||
if (gameRumbleCount>0 && !ConfigRequested) gameRumbleCount--;
|
||||
if (gameRumbleCount>0 && !InMenu) gameRumbleCount--;
|
||||
if (menuRumbleCount>0) menuRumbleCount--;
|
||||
}
|
||||
|
||||
@ -584,7 +575,7 @@ u32 DecodeKeyboard(unsigned short pad)
|
||||
#ifdef HW_RVL
|
||||
for (int i = 0; i < MAXJP; i++)
|
||||
{
|
||||
if (DownUsbKeys[btnmap[CTRLR_KEYBOARD][i]]) // keyboard
|
||||
if (DownUsbKeys[kbpadmap[i]]) // keyboard
|
||||
J |= vbapadmap[i];
|
||||
}
|
||||
#endif
|
||||
@ -597,7 +588,7 @@ u32 DecodeGamecube(unsigned short pad)
|
||||
u32 jp = PAD_ButtonsHeld(pad);
|
||||
for (int i = 0; i < MAXJP; i++)
|
||||
{
|
||||
if (jp & btnmap[CTRLR_GCPAD][i])
|
||||
if (jp & gcpadmap[i])
|
||||
J |= vbapadmap[i];
|
||||
}
|
||||
return J;
|
||||
@ -610,7 +601,7 @@ u32 DecodeWiimote(unsigned short pad)
|
||||
WPADData * wp = WPAD_Data(pad);
|
||||
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];
|
||||
}
|
||||
#endif
|
||||
@ -624,7 +615,7 @@ u32 DecodeClassic(unsigned short pad)
|
||||
WPADData * wp = WPAD_Data(pad);
|
||||
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];
|
||||
}
|
||||
#endif
|
||||
@ -638,7 +629,7 @@ u32 DecodeNunchuk(unsigned short pad)
|
||||
WPADData * wp = WPAD_Data(pad);
|
||||
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];
|
||||
}
|
||||
#endif
|
||||
@ -867,12 +858,12 @@ static u32 DecodeJoy(unsigned short pad)
|
||||
|
||||
for (i = 0; i < MAXJP; i++)
|
||||
{
|
||||
if ((jp & btnmap[CTRLR_GCPAD][i]) // gamecube controller
|
||||
if ((jp & gcpadmap[i]) // gamecube controller
|
||||
#ifdef HW_RVL
|
||||
|| ( (wp->exp.type == WPAD_EXP_NONE) && (wp->btns_h & btnmap[CTRLR_WIIMOTE][i]) ) // wiimote
|
||||
|| ( (wp->exp.type == WPAD_EXP_CLASSIC) && (wp->btns_h & btnmap[CTRLR_CLASSIC][i]) ) // classic controller
|
||||
|| ( (wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & btnmap[CTRLR_NUNCHUK][i]) ) // nunchuk + wiimote
|
||||
|| ( (DownUsbKeys[btnmap[CTRLR_KEYBOARD][i]]) ) // keyboard
|
||||
|| ( (wp->exp.type == WPAD_EXP_NONE) && (wp->btns_h & wmpadmap[i]) ) // wiimote
|
||||
|| ( (wp->exp.type == WPAD_EXP_CLASSIC) && (wp->btns_h & ccpadmap[i]) ) // classic controller
|
||||
|| ( (wp->exp.type == WPAD_EXP_NUNCHUK) && (wp->btns_h & ncpadmap[i]) ) // nunchuk + wiimote
|
||||
|| ( (DownUsbKeys[kbpadmap[i]]) ) // keyboard
|
||||
#endif
|
||||
)
|
||||
J |= vbapadmap[i];
|
||||
@ -886,11 +877,24 @@ u32 GetJoy(int pad)
|
||||
pad = 0;
|
||||
|
||||
s8 gc_px = PAD_SubStickX(0);
|
||||
s8 gc_py = PAD_SubStickY(0);
|
||||
|
||||
#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
|
||||
|
||||
// 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
|
||||
if ((gc_px < -70)
|
||||
#ifdef HW_RVL
|
||||
|
@ -12,11 +12,10 @@
|
||||
#define _INPUT_H_
|
||||
|
||||
#include <gccore.h>
|
||||
#include <wiiuse/wpad.h>
|
||||
|
||||
#define PI 3.14159265f
|
||||
#define PADCAL 50
|
||||
#define MAXJP 10 // # of mappable controller buttons
|
||||
#define MAXJP 10
|
||||
|
||||
#define VBA_BUTTON_A 1
|
||||
#define VBA_BUTTON_B 2
|
||||
@ -31,48 +30,13 @@
|
||||
#define VBA_SPEED 1024
|
||||
#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 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 ShutoffRumble();
|
||||
|