-internal wii game and channel banner playback, still work in

progress, thanks alot to dimok and the whole usb loader gx team 
for help and the code for it!
To zoom the banner to fullscreen click the back button, to zoom out
the back button again, known bugs:
-some games fuck up the textures of buttons (e.g. wii play motion)
-if no wii game or channel was selected and you try to launch a game
or exit wiiflow it will most likely codedump
This commit is contained in:
fix94.1 2012-07-03 16:26:49 +00:00
parent 757fd2021b
commit 706e18c6c0
42 changed files with 5089 additions and 21 deletions

View File

@ -18,6 +18,7 @@ include $(DEVKITPPC)/wii_rules
TARGET := boot
BUILD := build
SOURCES := source \
source/banner \
source/cheats \
source/config \
source/data \
@ -45,6 +46,7 @@ DATA := data \
data/help
INCLUDES := source \
source/banner \
source/cheats \
source/config \
source/devicemounter \

View File

@ -0,0 +1,174 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - Dimok
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include <malloc.h>
#include "U8Archive.h"
#include "LanguageCode.h"
#include "AnimatedBanner.h"
#include "text.hpp"
#include "lz77.h"
#include "ash.h"
AnimatedBanner::AnimatedBanner(u8 *font1, u8 *font2)
{
first = true;
layout_banner = NULL;
newBanner = NULL;
sysFont1 = font1;
sysFont2 = font2;
}
void AnimatedBanner::Clear()
{
if(first)
return;
if(layout_banner)
{
delete layout_banner;
layout_banner = NULL;
}
if(newBanner)
{
delete newBanner;
newBanner = NULL;
}
}
bool AnimatedBanner::LoadBanner(Banner *banner)
{
first = false;
Clear();
u32 banner_bin_size;
const u8 *banner_bin = banner->GetFile((char*)"banner.bin", &banner_bin_size);
if(banner_bin == NULL)
return false;
layout_banner = LoadLayout(banner_bin, banner_bin_size, "banner", CONF_GetLanguageString());
return (layout_banner != NULL);
}
Layout* AnimatedBanner::LoadLayout(const u8 *bnr, u32 bnr_size, const std::string& lyt_name, const std::string &language)
{
u32 brlyt_size = 0;
newBanner = DecompressCopy(bnr, bnr_size, &bnr_size);
const u8 *brlyt = u8_get_file(newBanner, (char*)fmt("%s.brlyt", lyt_name.c_str()), &brlyt_size);
if(!brlyt)
return NULL;
Layout *layout = new Layout(sysFont1, sysFont2);
layout->Load(brlyt);
u32 length_start = 0, length_loop = 0;
u32 brlan_start_size = 0;
const u8 *brlan_start = u8_get_file(newBanner, (char*)fmt("%s_Start.brlan", lyt_name.c_str()), &brlan_start_size);
const u8 *brlan_loop = 0;
// try the alternative file
if(!brlan_start)
brlan_start = u8_get_file(newBanner, (char*)fmt("%s_In.brlan", lyt_name.c_str()), &brlan_start_size);
if(brlan_start)
length_start = Animator::LoadAnimators((const RLAN_Header *)brlan_start, *layout, 0);
u32 brlan_loop_size = 0;
brlan_loop = u8_get_file(newBanner, (char*)fmt("%s.brlan", lyt_name.c_str()), &brlan_loop_size);
if(!brlan_loop)
brlan_loop = u8_get_file(newBanner, (char*)fmt("%s_Loop.brlan", lyt_name.c_str()), &brlan_loop_size);
if(!brlan_loop)
brlan_loop = u8_get_file(newBanner, (char*)fmt("%s_Rso0.brlan", lyt_name.c_str()), &brlan_loop_size); // added for "artstyle" wiiware
if(brlan_loop)
length_loop = Animator::LoadAnimators((const RLAN_Header *)brlan_loop, *layout, 1);
// load textures after loading the animations so we get the list of tpl filenames from the brlans
layout->LoadTextures(newBanner);
layout->LoadFonts(newBanner);
layout->SetLanguage(language);
layout->SetLoopStart(length_start);
layout->SetLoopEnd(length_start + length_loop);
layout->SetFrame(0);
return layout;
}
u8 *AnimatedBanner::DecompressCopy( const u8 * stuff, u32 len, u32 *size )
{
// check for IMD5 header and skip it
if( len > 0x40 && *(u32*)stuff == 0x494d4435 )// IMD5
{
stuff += 0x20;
len -= 0x20;
}
u8* ret = NULL;
// determine if it needs to be decompressed
if( IsAshCompressed( stuff, len ) )
{
//u32 len2 = len;
// ASH0
ret = DecompressAsh( stuff, len );
if( !ret )
{
gprintf( "out of memory\n" );
return NULL;
}
}
else if( isLZ77compressed( (u8*)stuff ) )
{
// LZ77 with no magic word
if( decompressLZ77content( (u8*)stuff, len, &ret, &len ) )
{
return NULL;
}
}
else if( *(u32*)( stuff ) == 0x4C5A3737 )// LZ77
{
// LZ77 with a magic word
if( decompressLZ77content( (u8*)stuff + 4, len - 4, &ret, &len ) )
{
return NULL;
}
}
else
{
// just copy the data out of the archive
ret = (u8*)memalign( 32, len );
if( !ret )
{
gprintf( "out of memory\n" );
return NULL;
}
memcpy( ret, stuff, len );
}
if( size )
{
*size = len;
}
// flush the cache so if there are any textures in this data, it will be ready for the GX
DCFlushRange( ret, len );
return ret;
}

View File

@ -0,0 +1,51 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - Dimok
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef _ANIMATEDBANNER_H_
#define _ANIMATEDBANNER_H_
#include "Layout.h"
#include "disc.h"
#include "channel/banner.h"
class AnimatedBanner
{
public:
AnimatedBanner(u8 *font1, u8 *font2);
void Clear();
bool LoadBanner(Banner *banner);
Layout *getBanner() const { return layout_banner; }
protected:
Layout* LoadLayout(const u8 *bnr, u32 bnr_size, const std::string& lyt_name, const std::string &language);
u8 *DecompressCopy( const u8 * stuff, u32 len, u32 *size );
Layout *layout_banner;
u8 *newBanner;
u8 *sysFont1;
u8 *sysFont2;
bool first;
};
#endif

260
source/banner/Animator.cpp Normal file
View File

@ -0,0 +1,260 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - Dimok
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include <math.h>
#include "Animator.h"
#include "Layout.h"
// load keyframes from a brlan file
u32 Animator::LoadAnimators(const RLAN_Header *header, Layout& layout, u8 key_set)
{
u32 frame_count = 0;
if (!header || header->magic != MAGIC_ANIMATION || header->endian != 0xFEFF || header->version != 0x0008)
return 0; // bad header
// first section
const u8 *position = ((const u8 *) header) + header->offset;
for(u32 i = 0; i < header->section_count; ++i)
{
section_t *section = (section_t *) position;
position += section->size;
if (section->magic == MAGIC_PANE_ANIMATION_INFO)
{
const PAI1_Header *pai = (const PAI1_Header *) section;
u16 animator_count = pai->animator_count;
frame_count += pai->frame_count;
// read animation file names
const u32 *nameOffsets = (const u32 *)(pai + 1);
for(u32 i = 0; i < pai->file_count; i++)
{
const char* name = (((const char *) nameOffsets) + nameOffsets[i]);
layout.AddPalette(name, key_set);
}
const u32 *offsets = (const u32 *) (((const u8 *)section) + pai->entry_offset);
// read each animator
for(u32 n = 0; n < animator_count; n++)
{
const AnimatorHeader *animHdr = (const AnimatorHeader *) (((const u8 *)section) + offsets[n]);
std::string anim_name(animHdr->name, 0, 20);
Animator* animator = animHdr->is_material ?
(Animator*) layout.FindMaterial(anim_name) :
(Animator*) layout.FindPane(anim_name);
if (animator)
animator->LoadKeyFrames((const u8 *) animHdr, animHdr->tag_count, sizeof(AnimatorHeader), key_set);
}
}
else
{
gprintf("Unknown: %c%c%c%c\n", position[0], position[1], position[2], position[3]);
}
}
return frame_count;
}
void Animator::LoadKeyFrames(const u8 *file, u8 tag_count, u32 offset, u8 key_set)
{
const u32 *tag_offsets = (const u32 *) (file + offset);
for(u32 tag = 0; tag < tag_count; tag++)
{
const Anim_Header *animHdr = (const Anim_Header *) (file + tag_offsets[tag]);
u32 animation_type = animHdr->animation_type;
u8 frame_count = animHdr->frame_count;
const u32 *frame_offsets = (const u32 *) (animHdr + 1);
for(u32 frame = 0; frame < frame_count; frame++)
{
const KeyFrame_Header *keyFrame = (const KeyFrame_Header *)(((const u8 *) animHdr) + frame_offsets[frame]);
const KeyType frame_type(static_cast<AnimationType>(animation_type), keyFrame->index, keyFrame->target);
switch (keyFrame->data_type)
{
// step key frame
case 0x01:
keys[key_set].step_keys[frame_type].Load((const u8 *) (keyFrame+1), keyFrame->key_count);
break;
// hermite key frame
case 0x02:
keys[key_set].hermite_keys[frame_type].Load((const u8 *) (keyFrame+1), keyFrame->key_count);
break;
default:
break;
}
}
}
}
void Animator::SetFrame(FrameNumber frame_number, u8 key_set)
{
std::map<KeyType, HermiteKeyHandler>::iterator itr;
for(itr = keys[key_set].hermite_keys.begin(); itr != keys[key_set].hermite_keys.end(); itr++)
{
const KeyType& frame_type = itr->first;
const float frame_value = itr->second.GetFrame(frame_number);
ProcessHermiteKey(frame_type, frame_value);
}
std::map<KeyType, StepKeyHandler>::iterator itr2;
for(itr2 = keys[key_set].step_keys.begin(); itr2 != keys[key_set].step_keys.end(); itr2++)
{
const KeyType& frame_type = itr2->first;
StepKeyHandler::KeyData const frame_data = itr2->second.GetFrame(frame_number);
ProcessStepKey(frame_type, frame_data);
}
}
void StepKeyHandler::Load(const u8 *file, u16 count)
{
while (count--)
{
FrameNumber frame;
frame = *((FrameNumber *) file);
file += 4;
KeyData& data = keys[frame];
data.data1 = *file;
file++;
data.data2 = *file;
file++;
file += 2;
}
}
void HermiteKeyHandler::Load(const u8 *file, u16 count)
{
while (count--)
{
std::pair<FrameNumber, KeyData> pair;
// read the frame number, value and slope
pair.first = *((FrameNumber *) file);
file += 4;
pair.second.value = *((float *) file);
file += 4;
pair.second.slope = *((float *) file);
file += 4;
keys.insert(pair);
//std::cout << "\t\t\t" "frame: " << frame << ' ' << keys[frame] << '\n';
}
}
StepKeyHandler::KeyData StepKeyHandler::GetFrame(FrameNumber frame_number) const
{
// assuming not empty, a safe assumption currently
// find the current frame, or the one after it
std::map<FrameNumber, KeyData>::const_iterator frame_it = keys.lower_bound(frame_number);
// current frame is higher than any keyframe, use the last keyframe
if (keys.end() == frame_it)
--frame_it;
// if this is after the current frame and not the first keyframe, use the previous one
if (frame_number < frame_it->first && keys.begin() != frame_it)
--frame_it;
return frame_it->second;
}
float HermiteKeyHandler::GetFrame(FrameNumber frame_number) const
{
// assuming not empty, a safe assumption currently
// find the current keyframe, or the one after it
std::multimap<FrameNumber, KeyData>::const_iterator next = keys.lower_bound(frame_number);
// current frame is higher than any keyframe, use the last keyframe
if (keys.end() == next)
--next;
std::multimap<FrameNumber, KeyData>::const_iterator prev = next;
// if this is after the current frame and not the first keyframe, use the previous one
if (frame_number < prev->first && keys.begin() != prev)
--prev;
const float nf = next->first - prev->first;
if (fabs(nf) < 0.01)
{
// same frame numbers, just return the first's value
return prev->second.value;
}
else
{
// different frames, blend them together
// this is a "Cubic Hermite spline" apparently
frame_number = (frame_number < prev->first) ? prev->first :
((frame_number > next->first) ? next->first : frame_number);
const float t = (frame_number - prev->first) / nf;
// old curve-less code
//return prev->second.value + (next->second.value - prev->second.value) * t;
// curvy code from marcan, :p
return
prev->second.slope * nf * (t + powf(t, 3) - 2 * powf(t, 2)) +
next->second.slope * nf * (powf(t, 3) - powf(t, 2)) +
prev->second.value * (1 + (2 * powf(t, 3) - 3 * powf(t, 2))) +
next->second.value * (-2 * powf(t, 3) + 3 * powf(t, 2));
}
}
void Animator::ProcessHermiteKey(const KeyType& type, float value)
{
// std::cout << "unhandled key (" << GetName() << "): type: " << FourCC(type.type)
// << " index: " << (int)type.index
// << " target: " << (int)type.target
// << " value: " << value
// << '\n';
gprintf("Animator::ProcessHermiteKey\n");
}
void Animator::ProcessStepKey(const KeyType& type, StepKeyHandler::KeyData data)
{
// std::cout << "unhandled key (" << GetName() << "): type: " << FourCC(type.type)
// << " index: " << (int)type.index
// << " target: " << (int)type.target
// << " data:" << (int)data.data1 << " " << (int)data.data2
// << '\n';
gprintf("Animator::ProcessStepKey\n");
}

169
source/banner/Animator.h Normal file
View File

@ -0,0 +1,169 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - Dimok
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef WII_BNR_ANIMATOR_H_
#define WII_BNR_ANIMATOR_H_
#include <map>
#include <cstring>
#include <string>
#include "BannerTools.h"
typedef float FrameNumber;
enum AnimationType
{
ANIMATION_TYPE_PANE = MAKE_FOURCC('R', 'L', 'P', 'A'),
ANIMATION_TYPE_TEXTURE_SRT = MAKE_FOURCC('R', 'L', 'T', 'S'),
ANIMATION_TYPE_VISIBILITY = MAKE_FOURCC('R', 'L', 'V', 'I'),
ANIMATION_TYPE_VERTEX_COLOR = MAKE_FOURCC('R', 'L', 'V', 'C'),
ANIMATION_TYPE_MATERIAL_COLOR = MAKE_FOURCC('R', 'L', 'M', 'C'),
ANIMATION_TYPE_TEXTURE_PALETTE = MAKE_FOURCC('R', 'L', 'T', 'P'),
ANIMATION_TYPE_IND_MATERIAL = MAKE_FOURCC('R', 'L', 'I', 'M'),
};
struct RLAN_Header
{
u32 magic;
u16 endian;
u16 version;
u32 file_size;
u16 offset;
u16 section_count;
} __attribute__((packed));
struct PAI1_Header
{
u32 magic;
u32 section_size;
u16 frame_count;
u8 loop;
u8 pad;
u16 file_count;
u16 animator_count;
u32 entry_offset;
} __attribute__((packed));
struct AnimatorHeader
{
char name[20];
u8 tag_count;
u8 is_material;
u16 apad;
} __attribute__((packed));
struct Anim_Header
{
u32 animation_type;
u8 frame_count;
u8 pad[3];
} __attribute__((packed));
struct KeyFrame_Header
{
u8 index;
u8 target;
u8 data_type;
u8 pad;
u16 key_count;
u16 pad1;
u32 offset;
} __attribute__((packed));
struct KeyType
{
KeyType(AnimationType _type, u8 _index, u8 _target)
: type(_type)
, index(_index)
, target(_target)
{}
bool operator<(const KeyType& rhs) const
{
return memcmp(this, &rhs, sizeof(*this)) < 0;
}
const AnimationType type;
const u8 index, target;
};
class StepKeyHandler
{
public:
void Load(const u8* file, u16 count);
struct KeyData
{
u8 data1, data2;
};
KeyData GetFrame(FrameNumber frame_number) const;
private:
std::map<FrameNumber, KeyData> keys;
};
class HermiteKeyHandler
{
public:
void Load(const u8* file, u16 count);
struct KeyData
{
float value, slope;
};
float GetFrame(FrameNumber frame_number) const;
private:
std::multimap<FrameNumber, KeyData> keys;
};
class Layout;
class Animator
{
public:
static const u32 MAGIC_ANIMATION = MAKE_FOURCC('R', 'L', 'A', 'N');
static const u32 MAGIC_PANE_ANIMATION_INFO = MAKE_FOURCC('p', 'a', 'i', '1');
static u32 LoadAnimators(const RLAN_Header *header, Layout& layout, u8 key_set);
void LoadKeyFrames(const u8 *file, u8 tag_count, u32 offset, u8 key_set);
virtual void SetFrame(FrameNumber frame, u8 key_set);
protected:
Animator() {}
virtual void ProcessHermiteKey(const KeyType& type, float value);
virtual void ProcessStepKey(const KeyType& type, StepKeyHandler::KeyData data);
private:
struct
{
std::map<KeyType, StepKeyHandler> step_keys;
std::map<KeyType, HermiteKeyHandler> hermite_keys;
} keys[2];
};
#endif

View File

@ -0,0 +1,148 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - Dimok
Copyright (c) 2012 - giantpune
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include <set>
#include <string.h>
#include <malloc.h>
#include "BannerTexture.hpp"
Texture::~Texture()
{
if(texture_data)
free(texture_data);
}
void Texture::Load(const u8 *file )
{
if(!file)
return;
header = (Texture::Header *) file;
if (header->magic != MAGIC) {
header = NULL;
return; // bad header
}
u32 texture_count = header->num_textures;
// only support a single texture
if (texture_count > 1)
{
// Never saw it happen
texture_count = 1;
gprintf("texture count > 1\n");
}
// read textures
const TPL_Texture *tpl_list = (const TPL_Texture *) (file + header->header_size);
for(u32 i = 0; i < texture_count; i++)
{
// seek to texture header
const TPL_Texture_Header *texture = (const TPL_Texture_Header *) (file + tpl_list[i].texture_offset);
u8 mipmap = 0;
u8 bias_clamp = 0;
if(texture->max_lod > 0)
mipmap = GX_TRUE;
if(texture->lod_bias > 0.0f)
bias_clamp = GX_ENABLE;
// texture data
u8 *texture_data = (u8 *) (file + texture->offset);
// seek to/read palette header
if (tpl_list[i].palette_offset != 0)
{
palette = (TPL_Palette_Header *) (file + tpl_list[i].palette_offset);
// load the texture
GX_InitTexObjCI(&texobj, texture_data, texture->width, texture->height, texture->format,
texture->wrap_s, texture->wrap_t, mipmap, 0);
}
else
{
// load the texture
GX_InitTexObj(&texobj, texture_data, texture->width, texture->height, texture->format,
texture->wrap_s, texture->wrap_t, mipmap);
}
// filter mode
if(mipmap)
{
GX_InitTexObjLOD(&texobj, texture->min, texture->mag, texture->min_lod, texture->max_lod,
texture->lod_bias, bias_clamp, bias_clamp, texture->edge_lod);
}
}
}
//! This function is to load custom texture data and replace the original one.
void Texture::LoadTextureData(const u8 *data, u16 width, u16 height, u8 fmt)
{
if(texture_data)
free(texture_data);
int tex_size = GX_GetTexBufferSize(width, height, fmt, GX_FALSE, 0);
texture_data = (u8*) memalign(32, tex_size);
if(!texture_data)
return;
memcpy(texture_data, data, tex_size);
DCFlushRange(texture_data, tex_size);
GX_InitTexObj(&texobj, texture_data, width, height, fmt, 0, 0, GX_FALSE);
}
void Texture::Apply(u8 &tlutName, u8 map_id, u8 wrap_s, u8 wrap_t) const
{
if(!header)
return;
if(tlutName >= 20 || map_id >= 8)
return;
// create a temporary texture object to not modify the original with the wrap_s and wrap_t parameters
GXTexObj tmpTexObj;
for(int i = 0; i < 8; ++i)
tmpTexObj.val[i] = texobj.val[i];
// assume that if there is a palette header, then this format is a CIx one
if(palette)
{
// seek to/read palette data
u8 *tlut_data = (u8 *) (((u8 *) header) + palette->offset);
// load tlut
GXTlutObj tlutobj;
GX_InitTlutObj(&tlutobj, tlut_data, palette->format, palette->num_items );
GX_LoadTlut(&tlutobj, tlutName);
GX_InitTexObjTlut((GXTexObj *) &tmpTexObj, tlutName);
tlutName++;
}
GX_InitTexObjWrapMode((GXTexObj *) &tmpTexObj, wrap_s, wrap_t);
GX_LoadTexObj((GXTexObj *) &tmpTexObj, map_id);
}

View File

@ -0,0 +1,102 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - Dimok
Copyright (c) 2012 - giantpune
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef TEXTURE_H_
#define TEXTURE_H_
#include <vector>
#include <string>
#include <gccore.h>
#include "BannerTools.h"
class Texture
{
public:
static const u32 MAGIC = MAKE_FOURCC(0x00, ' ', 0xAF, 0x30);
Texture() : header(NULL), palette(NULL), texture_data(NULL) {}
virtual ~Texture();
void Load(const u8 *texture);
const std::string &getName() const { return name; }
void setName(const std::string& _name) { name = _name; }
// load custom data into the texture object
void LoadTextureData(const u8 *data, u16 width, u16 height, u8 fmt);
void Apply(u8 &tlutName, u8 map_id, u8 wrap_s, u8 wrap_t) const;
private:
struct Header
{
u32 magic;
u32 num_textures;
u32 header_size;
} __attribute__((packed)) ;
struct TPL_Texture
{
u32 texture_offset;
u32 palette_offset;
} __attribute__((packed)) ;
struct TPL_Texture_Header
{
u16 height;
u16 width;
u32 format;
u32 offset;
u32 wrap_s;
u32 wrap_t;
u32 min;
u32 mag;
f32 lod_bias;
u8 edge_lod;
u8 min_lod;
u8 max_lod;
u8 unpacked;
} __attribute__((packed));
struct TPL_Palette_Header
{
u16 num_items;
u8 unpacked;
u8 pad;
u32 format;
u32 offset;
} __attribute__((packed));
Texture::Header *header;
TPL_Palette_Header *palette;
u8 *texture_data;
GXTexObj texobj;
std::string name;
};
class TextureList : public std::vector<Texture *>
{
public:
static const u32 MAGIC = MAKE_FOURCC('t', 'x', 'l', '1');
};
#endif

View File

@ -0,0 +1,61 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - Dimok
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef BANNER_TOOLS_H_
#define BANNER_TOOLS_H_
#include <gctypes.h>
#include "gecko.h"
#define MAKE_FOURCC(a, b, c, d) ((a) * (1 << 24) + (b) * (1 << 16) + (c) * (1 << 8) + (d) * (1 << 0))
typedef struct
{
u32 magic;
u32 size;
} section_t;
typedef struct
{
float x, y;
} Vec2f;
typedef struct
{
float x, y, z;
} Vec3f;
#define ALIGN32(x) (((x) + 31) & ~31)
#define LIMIT(x, min, max) \
({ \
typeof( x ) _x = x; \
typeof( min ) _min = min; \
typeof( max ) _max = max; \
( ( ( _x ) < ( _min ) ) ? ( _min ) : ( ( _x ) > ( _max ) ) ? ( _max) : ( _x ) ); \
})
#define MultiplyAlpha(a1, a2) ((u16) (a1) * (u16) (a2) / 0xFF)
#define FLOAT_2_U8(x) ((u8)((x) > 255.0f ? 255.0f : ((x) < 0.0f ? 0.0f : (x) + 0.5f)))
#define FLOAT_2_S16(x) ((s16)((x) > 32767.0f ? 32767.0f : ((x) < -32768.0f ? 32768.0f : (x) + 0.5f)))
#endif

View File

@ -0,0 +1,271 @@
/****************************************************************************
* Copyright (C) 2012 Dimok
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include <unistd.h>
#include "BannerWindow.hpp"
#include "menu.hpp"
#include "utils.h"
#include "gx_addons.h"
#include "gecko.h"
void BannerWindow::LoadBanner(Banner *banner, CVideo *vid, u8 *font1, u8 *font2)
{
MaxAnimSteps = 30;
returnVal = -1;
reducedVol = false;
ScreenProps.x = 620; //620
ScreenProps.y = 400; //400
sysFont1 = font1;
sysFont2 = font2;
video = vid;
guMtxIdentity(modelview);
guMtxTransApply(modelview, modelview, (!video->wide() || video->vid_50hz()) ? 0.0f : 2.0f, video->vid_50hz() ? -1.0f : 0.0f, 0.0F);
AnimPosX = 0.5f * (ScreenProps.x - fIconWidth);
AnimPosY = 0.5f * (ScreenProps.y - fIconHeight);
AnimZoomIn = false;
AnimZoomOut = false;
AnimationRunning = false;
BannerAlpha = 255.f;
ChangeGame(banner);
gameSelected = 1;
}
void BannerWindow::DeleteBanner()
{
gameSelected = 0;
gameBanner->Clear();
}
BannerWindow::BannerWindow()
{
AnimStep = 20;
gameSelected = 0;
firstRun = true;
}
void BannerWindow::ChangeGame(Banner *banner)
{
gameSelected = 0;
if(firstRun)
{
gameBanner = new AnimatedBanner(sysFont1, sysFont2);
firstRun = false;
}
gameBanner->LoadBanner(banner);
}
void BannerWindow::ZoomIn(void)
{
AnimZoomIn = true;
AnimZoomOut = false;
if(AnimStep <= 20)
AnimStep++;
}
void BannerWindow::PauseZoom(void)
{
AnimZoomIn = false;
AnimZoomOut = false;
}
void BannerWindow::ZoomOut(void)
{
AnimZoomIn = false;
AnimZoomOut = true;
if(AnimStep >= MaxAnimSteps)
AnimStep--;
}
void BannerWindow::Animate(void)
{
// animation is on going
if(AnimStep < MaxAnimSteps)
{
AnimationRunning = true;
if(AnimZoomIn && AnimStep < MaxAnimSteps)
AnimStep++;
else if(AnimZoomOut && AnimStep > 20)
AnimStep--;
/*
// zoom in animation
if(AnimZoomIn) {
BGAlpha = std::min(255.f * AnimStep * 2.f / MaxAnimSteps, 255.f);
//if(AnimStep < 0.4f * MaxAnimSteps)
//BannerAlpha = 0;
//else
//BannerAlpha = std::min(255.f * (AnimStep - 0.4f * MaxAnimSteps) / (0.6f * MaxAnimSteps), 255.f);
}
// zoom out animation
else {
BGAlpha = std::min(255.f * (MaxAnimSteps-AnimStep) * 2.f / MaxAnimSteps, 255.f);
//if((MaxAnimSteps - AnimStep) < 0.4f * MaxAnimSteps)
//BannerAlpha = 0;
//else
//BannerAlpha = std::min(255.f * ((MaxAnimSteps - AnimStep) - 0.4f * MaxAnimSteps) / (0.6f * MaxAnimSteps), 255.f);
}
*/
float curAnimStep = ((float)(MaxAnimSteps - AnimStep)/(float)MaxAnimSteps);
float stepx1 = -AnimPosX;
float stepy1 = -AnimPosY;
float stepx2 = (640 - 1) - (AnimPosX + fIconWidth);
float stepy2 = (480 - 1) - (AnimPosY + fIconHeight);
float top = AnimPosY + stepy1 * curAnimStep;
float bottom = AnimPosY + fIconHeight + stepy2 * curAnimStep;
float left = AnimPosX + stepx1 * curAnimStep;
float right = AnimPosX + fIconWidth + stepx2 * curAnimStep;
// set main projection of all GUI stuff if we are using the banner browser
//if(dynamic_cast<GuiBannerGrid *>(browserMenu->GetGameBrowser()) != NULL)
// guOrtho(FSProjection2D, top, bottom, left, right, 0, 10000);
float xDiff = 0.5f * (video->wide() ? (video->vid_50hz() ? 616 : 620.0f) : 608.0f);
float yDiff = 0.5f * (video->vid_50hz() ? 448.0f : 470.0f);
// this just looks better for banner/icon ratio
float iconWidth = fIconWidth - 20;
float iconHeight = fIconHeight - 20;
f32 ratioX = xDiff * 2.f / iconWidth;
f32 ratioY = yDiff * 2.f / iconHeight;
stepx1 = ((ScreenProps.x * 0.1f - xDiff) - (AnimPosX + 0.1f * fIconWidth - 0.1f * iconWidth)) * ratioX;
stepx2 = ((ScreenProps.x * 0.1f + xDiff) - (AnimPosX + 0.1f * fIconWidth + 0.1f * iconWidth)) * ratioX;
stepy1 = ((ScreenProps.y * 0.7f - yDiff) - (AnimPosY + 0.7f * fIconHeight - 0.7f * iconHeight)) * ratioY;
stepy2 = ((ScreenProps.y * 0.7f + yDiff) - (AnimPosY + 0.7f * fIconHeight + 0.7f * iconHeight)) * ratioY;
//! This works good for banners
top = (ScreenProps.y * 0.5f - yDiff) + stepy1 * curAnimStep;
bottom = (ScreenProps.y * 0.5f + yDiff) + stepy2 * curAnimStep;
left = (ScreenProps.x * 0.5f - xDiff) + stepx1 * curAnimStep;
right = (ScreenProps.x * 0.5f + xDiff) + stepx2 * curAnimStep;
// set banner projection
guOrtho(projection,top, bottom, left, right,-100,10000);
}
// last animation step
else if(AnimationRunning)
{
// set back original projection and stop animation/render of the browser (save some CPU ;P)
//memcpy(&video->projMtx, &originalProjection, sizeof(Mtx44));
AnimationRunning = false;
}
}
void BannerWindow::Draw(void)
{
// draw a black background image first
//DrawRectangle(0.0f, 0.0f, ScreenProps.x, ScreenProps.y, (GXColor) {0, 0, 0, BGAlpha}, true);
// Run window animation
Animate();
// no banner alpha means its the start of the animation
if(BannerAlpha == 0)
return;
// cut the unneeded crap
Mtx mv1, mv2, mv3;
guMtxIdentity(mv2);
guMtxIdentity(mv3);
guMtxScaleApply(modelview,mv1, 1.f, -1.f, 1.f);
guMtxTransApply(mv1,mv1, 0.5f * ScreenProps.x, 0.5f * ScreenProps.y, 0.f);
guMtxTransApply(mv2,mv2, -0.5f * fBannerWidth, 0.5f * fBannerHeight, 0.f);
guMtxTransApply(mv3,mv3, 0.5f * fBannerWidth, -0.5f * fBannerHeight, 0.f);
guMtxConcat(mv1, mv2, mv2);
guMtxConcat(mv1, mv3, mv3);
f32 viewportv[6];
f32 projectionv[7];
GX_GetViewportv(viewportv, video->vid_mode());
GX_GetProjectionv(projectionv, projection, GX_ORTHOGRAPHIC);
guVector vecTL;
guVector vecBR;
GX_Project(0.0f, 0.0f, 0.0f, mv2, projectionv, viewportv, &vecTL.x, &vecTL.y, &vecTL.z);
GX_Project(0.0f, 0.0f, 0.0f, mv3, projectionv, viewportv, &vecBR.x, &vecBR.y, &vecBR.z);
// round up scissor box offset and round down the size
u32 scissorX = (u32)(0.5f + std::max(vecTL.x, 0.0f));
u32 scissorY = (u32)(0.5f + std::max(vecTL.y, 0.0f));
u32 scissorW = (u32)std::max(vecBR.x - vecTL.x, 0.0f);
u32 scissorH = (u32)std::max(vecBR.y - vecTL.y, 0.0f);
GX_SetScissor(scissorX, scissorY, scissorW, scissorH);
// load projection matrix
GX_LoadProjectionMtx(projection, GX_ORTHOGRAPHIC);
if(gameBanner->getBanner())
{
gameBanner->getBanner()->Render(modelview, ScreenProps, video->wide(), BannerAlpha);
gameBanner->getBanner()->AdvanceFrame();
}
//if(AnimationRunning)
GX_SetScissor(0, 0, video->width(), video->height());
// Clear and back to previous projection
video->setup2DProjection();
GX_InvVtxCache();
GX_InvalidateTexAll();
}
void BannerWindow::DrawRectangle(f32 x, f32 y, f32 width, f32 height, GXColor color, u8 filled)
{
Mtx modelViewMtx;
guMtxIdentity(modelViewMtx);
GX_LoadPosMtxImm(modelViewMtx, GX_PNMTX0);
GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
GX_ClearVtxDesc();
GX_InvVtxCache();
GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT);
GX_SetVtxDesc(GX_VA_TEX0, GX_NONE);
u8 fmt;
long n;
int i;
f32 x2 = x + width;
f32 y2 = y + height;
guVector v[] = { { x, y, 0.0f }, { x2, y, 0.0f }, { x2, y2, 0.0f }, { x, y2, 0.0f }, { x, y, 0.0f } };
if (!filled)
{
fmt = GX_LINESTRIP;
n = 5;
}
else
{
fmt = GX_TRIANGLEFAN;
n = 4;
}
GX_Begin(fmt, GX_VTXFMT0, n);
for (i = 0; i < n; i++)
{
GX_Position3f32(v[i].x, v[i].y, v[i].z);
GX_Color4u8(color.r, color.g, color.b, color.a);
}
GX_End();
GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE);
}

View File

@ -0,0 +1,82 @@
/****************************************************************************
* Copyright (C) 2012 Dimok
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef BANNERWINDOW_HPP_
#define BANNERWINDOW_HPP_
#include <gccore.h>
#include "disc.h"
#include "AnimatedBanner.h"
#include "gui_sound.h"
#include "video.hpp"
#include "channel/banner.h"
#define FAVORITE_STARS 5
class BannerWindow
{
public:
BannerWindow();
void DeleteBanner();
void LoadBanner(Banner *banner, CVideo *vid, u8 *font1, u8 *font2);
int GetSelectedGame() { return gameSelected; }
void Draw(void);
void ZoomIn(void);
void PauseZoom(void);
void ZoomOut(void);
protected:
int MainLoop();
void Animate(void);
void ChangeGame(Banner *banner);
void DrawRectangle(f32 x, f32 y, f32 width, f32 height, GXColor color, u8 filled);
static const float fBannerWidth = 608.f;
static const float fBannerHeight = 448.f;
static const float fIconWidth = 128.f;
static const float fIconHeight = 96.f;
CVideo *video;
bool reducedVol;
int returnVal;
int gameSelected;
dir_discHdr dvdheader;
int MaxAnimSteps;
int AnimStep;
float AnimPosX, AnimPosY;
float fAnimScale;
bool AnimZoomIn;
bool AnimZoomOut;
bool AnimationRunning;
bool oldAnimationRunning;
bool firstRun;
u8 BGAlpha;
u8 BannerAlpha;
Mtx modelview;
Mtx44 projection;
Mtx44 originalProjection;
Vec2f ScreenProps;
AnimatedBanner *gameBanner;
u8 *sysFont1;
u8 *sysFont2;
};
#endif

View File

@ -0,0 +1,26 @@
#include <gccore.h>
const char* CONF_GetLanguageString(void)
{
static int confLang = 0xdead;
if(confLang == 0xdead)
confLang = CONF_GetLanguage();
const char*lang;
switch( confLang )
{
case CONF_LANG_JAPANESE: lang = "JPN"; break;
default:
case CONF_LANG_ENGLISH: lang = "ENG"; break;
case CONF_LANG_GERMAN: lang = "GER"; break;
case CONF_LANG_FRENCH: lang = "FRA"; break;
case CONF_LANG_SPANISH: lang = "SPA"; break;
case CONF_LANG_ITALIAN: lang = "ITA"; break;
case CONF_LANG_DUTCH: lang = "NED"; break;
case CONF_LANG_SIMP_CHINESE:
case CONF_LANG_TRAD_CHINESE: lang = "CHN"; break;
case CONF_LANG_KOREAN: lang = "KOR"; break;
}
return lang;
}

View File

@ -0,0 +1,14 @@
#ifndef __LANGUAGE_CODE_H_
#define __LANGUAGE_CODE_H_
#ifdef __cplusplus
extern "C" {
#endif
const char* CONF_GetLanguageString(void);
#ifdef __cplusplus
}
#endif
#endif

392
source/banner/Layout.cpp Normal file
View File

@ -0,0 +1,392 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - Dimok
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Layout.h"
#include "WiiFont.h"
#include "U8Archive.h"
Layout::Layout(u8 *font1, u8 *font2)
: header(0)
{
Wbf1Font = font1;
Wbf2Font = font2;
}
Layout::~Layout()
{
for(u32 i = 0; i < panes.size(); ++i)
delete panes[i];
for(u32 i = 0; i < resources.materials.size(); ++i)
delete resources.materials[i];
for(u32 i = 0; i < resources.textures.size(); ++i)
delete resources.textures[i];
for(u32 i = 0; i < resources.fonts.size(); ++i)
delete resources.fonts[i];
}
bool Layout::Load(const u8 *brlyt)
{
if(!brlyt)
return false;
const BRLYT_Header *brlytFile = (const BRLYT_Header *) brlyt;
if(brlytFile->magic != BRLYT_MAGIC || brlytFile->version != BRLYT_VERSION)
return false;
Group* last_group = NULL;
std::stack<std::map<std::string, Group>*> group_stack;
group_stack.push(&groups);
Pane* last_pane = NULL;
std::stack<std::vector<Pane*>*> pane_stack;
pane_stack.push(&panes);
const u8 *position = brlyt + brlytFile->header_len;
for(u32 i = 0; i < brlytFile->section_count; ++i)
{
section_t *section = (section_t *) position;
position += section->size;
if(section->magic == Layout::MAGIC)
{
header = (Layout::Header *) (section + 1);
}
else if (section->magic == TextureList::MAGIC)
{
const LytItemList *txl1 = (const LytItemList *) (section+1);
const char *nameoffset = ((const char *)(txl1+1));
const LytStringTable *stringTable = (const LytStringTable *) (((const u8 *)(txl1+1))+txl1->offset_to_first);
for(u32 i = 0; i < txl1->num_items; ++i)
{
const char *name = nameoffset+stringTable[i].offset_filename;
Texture *texture = new Texture;
texture->setName(name);
resources.textures.push_back(texture);
}
}
else if (section->magic == MaterialList::MAGIC)
{
const LytItemList *mat1 = (const LytItemList *) (section+1);
const u32 *mat_offsets = (const u32 *) (((const u8 *)(mat1+1))+mat1->offset_to_first);
for(u32 i = 0; i < mat1->num_items; ++i)
{
Material *material = new Material;
material->Load((Material::Header *) (((const u8 *) section)+mat_offsets[i]));
resources.materials.push_back(material);
}
}
else if (section->magic == FontList::MAGIC)
{
// load font list
const LytItemList *fnl1 = (const LytItemList *) (section+1);
const char *nameoffset = ((const char *)(fnl1+1));
const LytStringTable *stringTable = (const LytStringTable *) (((const u8 *)(fnl1+1))+fnl1->offset_to_first);
for(u32 i = 0; i < fnl1->num_items; i++)
{
const char *name = nameoffset+stringTable[i].offset_filename;
WiiFont *font;
if(strcmp(name, "wbf1.brfna") == 0 || strcmp(name, "RevoIpl_RodinNTLGPro_DB_32_I4.brfnt") == 0) {
//! 1st system font or alias for it
font = new WiiFont;
font->SetName("wbf1.brfna");
font->Load(Wbf1Font);
if(!font) continue;
}
else if(strcmp(name, "wbf2.brfna") == 0) {
//! 2nd system font
font = new WiiFont;
font->SetName("wbf2.brfna");
font->Load(Wbf2Font);
if(!font) continue;
}
else {
//! font from banner
font = new WiiFont;
font->SetName(name);
}
resources.fonts.push_back(font);
}
}
else if (section->magic == Pane::MAGIC)
{
Pane* pane = new Pane;
pane->Load((Pane::Header *) section);
pane_stack.top()->push_back(last_pane = pane);
}
else if (section->magic == Bounding::MAGIC)
{
Bounding* pane = new Bounding;
pane->Load((Pane::Header *) section);
pane_stack.top()->push_back(last_pane = pane);
}
else if (section->magic == Picture::MAGIC)
{
Picture* pane = new Picture;
pane->Load((Pane::Header *) section);
pane_stack.top()->push_back(last_pane = pane);
}
else if (section->magic == Window::MAGIC)
{
Window* pane = new Window;
pane->Load((Pane::Header *) section);
pane_stack.top()->push_back(last_pane = pane);
}
else if (section->magic == Textbox::MAGIC)
{
Textbox* pane = new Textbox;
pane->Load((Pane::Header *) section);
pane_stack.top()->push_back(last_pane = pane);
}
else if (section->magic == Layout::MAGIC_PANE_PUSH)
{
if (last_pane)
pane_stack.push(&last_pane->panes);
}
else if (section->magic == Layout::MAGIC_PANE_POP)
{
if (pane_stack.size() > 1)
pane_stack.pop();
}
else if (section->magic == Group::MAGIC)
{
const char *grp = (const char *) (section + 1);
std::string group_name(grp, 0, Layout::Group::NAME_LENGTH);
Group& group_ref = (*group_stack.top())[group_name];
grp += Layout::Group::NAME_LENGTH;
u16 sub_count = *(u16 *) grp;
grp += 4; // 2 bytes reserved
while (sub_count--)
{
std::string pane_name(grp, 0, Layout::Group::NAME_LENGTH);
group_ref.panes.push_back(pane_name);
grp += Layout::Group::NAME_LENGTH;
}
last_group = &group_ref;
}
else if (section->magic == Layout::MAGIC_GROUP_PUSH)
{
if (last_group)
group_stack.push(&last_group->groups);
}
else if (section->magic == Layout::MAGIC_GROUP_POP)
{
if (group_stack.size() > 1)
group_stack.pop();
}
else {
gprintf("Uknown layout section: %08X\n", section->magic);
}
}
return true;
}
bool Layout::LoadTextures(const u8 *banner_file)
{
bool success = false;
for(u32 i = 0; i < resources.textures.size(); ++i)
{
u32 filesize;
const u8 *file = u8_get_file(banner_file, resources.textures[i]->getName().c_str(), &filesize);
if (file)
resources.textures[i]->Load(file);
else
success = false;
}
return success;
}
bool Layout::LoadFonts(const u8 *banner_file)
{
bool success = false;
for(u32 i = 0; i < resources.fonts.size(); ++i)
{
if(resources.fonts[i]->IsLoaded())
continue;
u32 filesize;
const u8 *file = u8_get_file(banner_file, resources.fonts[i]->getName().c_str(), &filesize);
if (file)
resources.fonts[i]->Load(file);
else
success = false;
}
return success;
}
void Layout::Render(Mtx &modelview, const Vec2f &ScreenProps, bool widescreen, u8 render_alpha) const
{
if(!header)
return;
Mtx mv;
// we draw inverse
guMtxScaleApply(modelview, mv, 1.0f, -1.0f, 1.0f);
// centered draw
if(header->centered)
guMtxTransApply(mv, mv, ScreenProps.x * 0.5f, ScreenProps.y * 0.5f, 0.f);
// render all panes
for(u32 i = 0; i < panes.size(); ++i)
panes[i]->Render(resources, render_alpha, mv, widescreen);
}
void Layout::SetFrame(FrameNumber frame_number)
{
frame_current = frame_number;
const u8 key_set = (frame_current >= frame_loop_start);
if (key_set)
frame_number -= frame_loop_start;
resources.cur_set = key_set;
for(u32 i = 0; i < panes.size(); ++i)
panes[i]->SetFrame(frame_number, key_set);
for(u32 i = 0; i < resources.materials.size(); ++i)
resources.materials[i]->SetFrame(frame_number, key_set);
}
void Layout::AdvanceFrame()
{
++frame_current;
if (frame_current >= frame_loop_end)
frame_current = frame_loop_start;
SetFrame(frame_current);
}
void Layout::SetLanguage(const std::string& language)
{
if(!header)
return;
// check if that language is found
bool lang_found = false;
// hide panes of non-matching languages
std::map<std::string, Group>::iterator itr;
for(itr = groups["RootGroup"].groups.begin(); itr != groups["RootGroup"].groups.end(); itr++)
{
// check if that language exists
if(!lang_found && itr->first == language)
lang_found = true;
// some hax, there are some odd "Rso0" "Rso1" groups that shouldn't be hidden
// only the 3 character language groups should be
if (itr->first != language && itr->first.length() == 3)
{
std::list<std::string>::iterator itr2;
for(itr2 = itr->second.panes.begin(); itr2 != itr->second.panes.end(); itr2++)
{
Pane* const found = FindPane(*itr2);
if (found)
found->SetHide(true);
}
}
}
// show english if langauge is not found
if(!lang_found && language != "ENG")
{
SetLanguage("ENG");
return;
}
// unhide panes of matching language, some banners list language specific panes in multiple language groups
std::list<std::string>::iterator itr2;
for(itr2 = groups["RootGroup"].groups[language].panes.begin(); itr2 != groups["RootGroup"].groups[language].panes.end(); itr2++)
{
Pane* const found = FindPane(*itr2);
if (found)
{
found->SetHide(false);
found->SetVisible(true); // all games with languages start as visible
}
}
}
void Layout::AddPalette(const std::string &name, u8 key_set)
{
resources.palettes[key_set].push_back(name);
if(FindTexture(name) != 0)
return;
Texture *texture = new Texture;
texture->setName(name);
resources.textures.push_back(texture);
}
Pane* Layout::FindPane(const std::string& find_name)
{
for(u32 i = 0; i < panes.size(); ++i)
{
Pane* found = panes[i]->FindPane(find_name);
if(found)
return found;
}
return NULL;
}
Material* Layout::FindMaterial(const std::string& find_name)
{
for(u32 i = 0; i < resources.materials.size(); ++i)
{
if (find_name.compare(0, 20, resources.materials[i]->getName()) == 0)
return resources.materials[i];
}
return NULL;
}
Texture* Layout::FindTexture(const std::string& find_name)
{
for(u32 i = 0; i < resources.textures.size(); ++i)
{
if (find_name == resources.textures[i]->getName())
return resources.textures[i];
}
return NULL;
}

145
source/banner/Layout.h Normal file
View File

@ -0,0 +1,145 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - Dimok
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef LAYOUT_H_
#define LAYOUT_H_
#include <gctypes.h>
#include <map>
#include <string>
#include <list>
#include <stack>
#include "BannerTexture.hpp"
#include "Material.h"
#include "Pane.h"
#include "Picture.h"
#include "Window.h"
#include "WiiFont.h"
#include "Textbox.h"
typedef std::vector<std::string> PaletteList;
struct BannerResources
{
MaterialList materials;
TextureList textures;
FontList fonts;
PaletteList palettes[2];
u8 cur_set;
};
class Layout
{
public:
Layout(u8 *font1, u8* font2);
virtual ~Layout();
static const u32 BRLYT_MAGIC = MAKE_FOURCC('R', 'L', 'Y', 'T');
static const u32 BRLYT_VERSION = 0xFEFF0008;
static const u32 MAGIC = MAKE_FOURCC('l', 'y', 't', '1');
static const u32 MAGIC_PANE_PUSH = MAKE_FOURCC('p', 'a', 's', '1');
static const u32 MAGIC_PANE_POP = MAKE_FOURCC('p', 'a', 'e', '1');
static const u32 MAGIC_GROUP_PUSH = MAKE_FOURCC('g', 'r', 's', '1');
static const u32 MAGIC_GROUP_POP = MAKE_FOURCC('g', 'r', 'e', '1');
bool Load(const u8 *brlyt);
bool LoadTextures(const u8 *banner_file);
bool LoadFonts(const u8 *banner_file);
void Render(Mtx &modelview, const Vec2f &ScreenProps, bool widescreen, u8 render_alpha = 0xFF) const;
FrameNumber GetFrame() const { return frame_current; }
void SetFrame(FrameNumber frame_number);
void AdvanceFrame();
void SetLoopStart(FrameNumber loop_start) { frame_loop_start = loop_start; }
void SetLoopEnd(FrameNumber loop_end) { frame_loop_end = loop_end; }
float GetWidth() const { return header->width; }
void SetWidth(float _width) { header->width = _width; }
float GetHeight() const { return header->height; }
void SetHeight(float _height) { header->height = _height; }
bool isCentered() const { return header->centered; }
void SetLanguage(const std::string& language);
Pane* FindPane(const std::string& name);
Material* FindMaterial(const std::string& name);
Texture *FindTexture(const std::string &name);
void AddPalette(const std::string &name, u8 key_set);
protected:
struct BRLYT_Header
{
u32 magic;
u32 version;
u32 filesize;
u16 header_len;
u16 section_count;
} __attribute__((packed));
struct Header
{
u8 centered;
u8 pad[3];
float width;
float height;
} __attribute__((packed));
struct LytItemList
{
u16 num_items;
u16 offset_to_first;
} __attribute__((packed));
struct LytStringTable
{
u32 offset_filename;
u32 pad;
} __attribute__((packed));
struct Group
{
static const u32 MAGIC = MAKE_FOURCC('g', 'r', 'p', '1');
static const u32 NAME_LENGTH = 0x10;
std::map<std::string, Group> groups;
std::list<std::string> panes;
};
Layout::Header *header;
u8 *Wbf1Font;
u8 *Wbf2Font;
BannerResources resources;
PaneList panes;
FrameNumber frame_current, frame_loop_start, frame_loop_end;
std::map<std::string, Group> groups;
};
#endif

591
source/banner/Material.cpp Normal file
View File

@ -0,0 +1,591 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - Dimok and giantpune
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include <algorithm>
#include <math.h>
#include "Layout.h"
#include "Material.h"
Material::Material()
: flags(0)
, texture_maps(0)
, texture_srts(0)
, texture_coord_gens(0)
, chan_control(0)
, mat_color(0)
, tev_swap_table(0)
, ind_srt(0)
, ind_stage(0)
, tev_stages(0)
, alpha_compare(0)
, blend_mode(0)
, header(0)
{
for( int i = 0; i < 8; i++ )
palette_texture[i] = DEFAULT_PALETTE;
}
void Material::Load(Material::Header *file)
{
header = file;
// Flags
flags = (MatFlags *) &header->flags;
flags->texture_map = std::min((int)MAX_TEX_MAP, (int)flags->texture_map);
flags->texture_srt = std::min((int)MAX_TEX_SRT, (int)flags->texture_srt);
flags->texture_coord_gen = std::min((int)MAX_TEX_GEN, (int)flags->texture_coord_gen);
flags->ind_srt = flags->ind_srt;
flags->ind_stage = std::min((int)MAX_IND_STAGES, (int)flags->ind_stage);
flags->tev_stages = std::min((int)MAX_TEV_STAGES, (int)flags->tev_stages);
u8 *buf_offset = (u8 *) (header+1);
// texture map
if(flags->texture_map)
{
texture_maps = (TextureMap *) buf_offset;
buf_offset += sizeof(TextureMap) * flags->texture_map;
}
// texture srt
if(flags->texture_srt)
{
texture_srts = (TextureSrt *) buf_offset;
buf_offset += sizeof(TextureSrt) * flags->texture_srt;
}
// texture coord gen
if(flags->texture_coord_gen)
{
texture_coord_gens = (TextureCoordGen *) buf_offset;
buf_offset += sizeof(TextureCoordGen) * flags->texture_coord_gen;
}
// channel control
if (flags->channel_control)
{
chan_control = (ChannelControl *) buf_offset;
buf_offset += sizeof(ChannelControl);
}
// material color
if (flags->material_color)
{
mat_color = (GXColor *) buf_offset;
buf_offset += sizeof(GXColor);
}
//else Default to 0xFFFFFFFF
// tev swap table
if (flags->tev_swap_table)
{
tev_swap_table = (TevSwap *) buf_offset;
buf_offset += sizeof(TevSwap) * 4;
}
// ind srt
if(flags->ind_srt)
{
ind_srt = (IndSrt *) buf_offset;
buf_offset += sizeof(IndSrt) * flags->ind_srt;
}
// ind stage
if(flags->ind_stage)
{
ind_stage = (IndStage *) buf_offset;
buf_offset += sizeof(IndStage) * flags->ind_stage;
}
// tev stage
if(flags->tev_stages)
{
tev_stages = (TevStage *) buf_offset;
buf_offset += sizeof(TevStage) * flags->tev_stages;
}
// alpha compare
if (flags->alpha_compare)
{
alpha_compare = (AlphaCompareModes *) buf_offset;
buf_offset += sizeof(AlphaCompareModes);
}
// blend mode
if (flags->blend_mode)
{
blend_mode = (BlendModes *) buf_offset;
buf_offset += sizeof(BlendModes);
}
}
inline void Material::ApplyChannelControl(u8 render_alpha, bool &modulate_colors) const
{
if(flags->channel_control)
{
GX_SetChanCtrl(0, 0, 0, chan_control->color_matsrc, 0, 0, 2 );
GX_SetChanCtrl(2, 0, 0, chan_control->alpha_matsrc, 0, 0, 2 );
if(chan_control->alpha_matsrc != 1 && chan_control->color_matsrc != 1)
modulate_colors = false;
if(!chan_control->alpha_matsrc || !chan_control->color_matsrc)
{
GXColor matColor = (GXColor){0xff, 0xff, 0xff, MultiplyAlpha(0xff, render_alpha) };
if(flags->material_color)
matColor = (GXColor){ mat_color->r, mat_color->g, mat_color->b,
MultiplyAlpha(mat_color->a, render_alpha) };
GX_SetChanMatColor(4, matColor);
if((*(u32 *)&matColor) == 0xFFFFFFFF)
modulate_colors = true;
}
}
else
{
GX_SetChanCtrl(4, 0, 0, 1, 0, 0, 2);
}
GX_SetNumChans(1);
}
inline void Material::ApplyTexCoordGens(void) const
{
// texture coord gen
for(u32 i = 0; i != flags->texture_coord_gen; ++i)
{
const TextureCoordGen &tcg = texture_coord_gens[i];
GX_SetTexCoordGen(GX_TEXCOORD0 + i, tcg.tgen_typ, tcg.tgen_src, tcg.mtxsrc);
const u8 mtrx = (tcg.mtxsrc - GX_TEXMTX0) / 3;
if (tcg.tgen_typ == 1 && tcg.mtxsrc != GX_IDENTITY && mtrx < flags->texture_srt)
{
const TextureSrt& srt = texture_srts[mtrx];
const float rotate_rad = DegToRad(srt.rotate);
const float cosF = cosf(rotate_rad);
const float sinF = sinf(rotate_rad);
// setup texture matrix
Mtx m;
m[0][0] = srt.scale_x * cosF;
m[0][1] = srt.scale_y * -sinF;
m[0][2] = 0.0f;
m[0][3] = -0.5f * (m[0][0] + m[0][1]) + srt.translate_x + 0.5f;
m[1][0] = srt.scale_x * sinF;
m[1][1] = srt.scale_y * cosF;
m[1][2] = 0.0f;
m[1][3] = -0.5f * (m[1][0] + m[1][1]) + srt.translate_y + 0.5f;
m[2][0] = 0.0f;
m[2][1] = 0.0f;
m[2][2] = 1.0f;
m[2][3] = 0.0f;
GX_LoadTexMtxImm(m, tcg.mtxsrc, GX_MTX3x4);
}
}
GX_SetNumTexGens(flags->texture_coord_gen);
}
inline void Material::ApplyTevSwapTable(void) const
{
if (flags->tev_swap_table)
{
for(int i = 0; i < 4; i++)
GX_SetTevSwapModeTable(GX_TEV_SWAP0 + i,
tev_swap_table[i].r, tev_swap_table[i].g,
tev_swap_table[i].b, tev_swap_table[i].a);
}
else
{
GX_SetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA);
GX_SetTevSwapModeTable(GX_TEV_SWAP1, GX_CH_RED, GX_CH_RED, GX_CH_RED, GX_CH_ALPHA);
GX_SetTevSwapModeTable(GX_TEV_SWAP2, GX_CH_GREEN, GX_CH_GREEN, GX_CH_GREEN, GX_CH_ALPHA);
GX_SetTevSwapModeTable(GX_TEV_SWAP3, GX_CH_BLUE, GX_CH_BLUE, GX_CH_BLUE, GX_CH_ALPHA);
}
}
inline void Material::ApplyTevStages(bool modulate_colors) const
{
u32 tev_stages_cnt = 0;
if(flags->tev_stages)
{
// tev stages
for(u32 i = 0; i < flags->tev_stages; ++i)
{
const TevStage &ts = tev_stages[i];
GX_SetTevOrder(i, ts.texcoord, ts.tex_map | (ts.lowBit << 8), ts.color );
GX_SetTevSwapMode(i, ts.ras_sel, ts.tex_sel);
GX_SetTevColorIn(i, ts.color_in.a, ts.color_in.b, ts.color_in.c, ts.color_in.d);
GX_SetTevColorOp(i, ts.color_in.tevop, ts.color_in.tevbias, ts.color_in.tevscale, ts.color_in.clamp, ts.color_in.tevregid );
GX_SetTevKColorSel(i, ts.color_in.sel );
GX_SetTevAlphaIn(i, ts.alpha_in.a, ts.alpha_in.b, ts.alpha_in.c, ts.alpha_in.d);
GX_SetTevAlphaOp(i, ts.alpha_in.tevop, ts.alpha_in.tevbias, ts.alpha_in.tevscale, ts.alpha_in.clamp, ts.alpha_in.tevregid );
GX_SetTevKAlphaSel(i, ts.alpha_in.sel );
GX_SetTevIndirect(i, ts.ind.indtexid, ts.ind.format, ts.ind.bias, ts.ind.mtxid,
ts.ind.wrap_s, ts.ind.wrap_t, ts.ind.addprev, ts.ind.utclod, ts.ind.a);
tev_stages_cnt++;
}
}
else
{
if(flags->texture_map == 0)
{
// 1st stage
GX_SetTevOrder(GX_TEVSTAGE0, 0xFF, 0xFF, 4);
GX_SetTevColorIn(GX_TEVSTAGE0, 0xF, 4, 0xA, 0xF);
GX_SetTevAlphaIn(GX_TEVSTAGE0, 0x7, 2, 0x5, 0x7);
tev_stages_cnt++;
}
else if(flags->texture_map == 1)
{
// 1st stage
GX_SetTevOrder(GX_TEVSTAGE0, 0, 0, 0xFF);
GX_SetTevColorIn(GX_TEVSTAGE0, 2, 4, 8, 0xF);
GX_SetTevAlphaIn(GX_TEVSTAGE0, 1, 2, 4, 7);
tev_stages_cnt++;
// 2nd stage
if(modulate_colors)
{
GX_SetTevOrder(GX_TEVSTAGE0 + tev_stages_cnt, 0xFF, 0xFF, 4);
GX_SetTevColorIn(GX_TEVSTAGE0 + tev_stages_cnt, 0xF, 0, 0xA, 0xF);
GX_SetTevAlphaIn(GX_TEVSTAGE0 + tev_stages_cnt, 7, 0, 5, 7);
tev_stages_cnt++;
}
}
else if(flags->texture_map == 2)
{
// 1st stage
GX_SetTevOrder(GX_TEVSTAGE0, 0, 0, 0xFF);
GX_SetTevColorIn(GX_TEVSTAGE0, 0xF, 0xF, 0xF, 8);
GX_SetTevAlphaIn(GX_TEVSTAGE0, 7, 7, 7, 4);
tev_stages_cnt++;
// 2nd stage
GX_SetTevOrder(GX_TEVSTAGE0 + tev_stages_cnt, 1, 1, 0xFF);
GX_SetTevColorIn(GX_TEVSTAGE0 + tev_stages_cnt, 8, 0, 0xE, 0xF);
GX_SetTevAlphaIn(GX_TEVSTAGE0 + tev_stages_cnt, 4, 0, 6, 7);
GX_SetTevKColorSel(GX_TEVSTAGE0 + tev_stages_cnt, 0x1f);
GX_SetTevKAlphaSel(GX_TEVSTAGE0 + tev_stages_cnt, 0x1f);
tev_stages_cnt++;
// 3rd stage
if(modulate_colors)
{
GX_SetTevOrder(GX_TEVSTAGE0 + tev_stages_cnt, 0xFF, 0xFF, 4);
GX_SetTevColorIn(GX_TEVSTAGE0 + tev_stages_cnt, 0xF, 0, 0xA, 0xF);
GX_SetTevAlphaIn(GX_TEVSTAGE0 + tev_stages_cnt, 7, 0, 5, 7);
tev_stages_cnt++;
}
}
else
{
u32 TevKDefault[] = { 0x1F, 0x1B, 0x17, 0x13, 0x1E, 0x1A, 0x16, 0x12 };
for(int i = 0; i < flags->texture_map; i++)
{
GX_SetTevOrder(i, i, i, 0xff );
GX_SetTevColorIn(i, 0xf, 8, 0xe, i ? 0xf : 0 );
GX_SetTevAlphaIn(i, 7, 4, 6, i ? 7 : 0 );
GX_SetTevKColorSel(i, TevKDefault[i] );
GX_SetTevKAlphaSel(i, TevKDefault[i] );
tev_stages_cnt++;
}
GX_SetTevOrder(GX_TEVSTAGE0 + tev_stages_cnt, 0xff, 0xff, 0xff );
GX_SetTevColorIn(GX_TEVSTAGE0 + tev_stages_cnt, 2, 4, 0, 0xf );
GX_SetTevAlphaIn(GX_TEVSTAGE0 + tev_stages_cnt, 1, 2, 0, 7 );
tev_stages_cnt++;
if(modulate_colors)
{
GX_SetTevOrder(GX_TEVSTAGE0 + tev_stages_cnt, 0xFF, 0xFF, 4);
GX_SetTevColorIn(GX_TEVSTAGE0 + tev_stages_cnt, 0xF, 0, 0xA, 0xF);
GX_SetTevAlphaIn(GX_TEVSTAGE0 + tev_stages_cnt, 7, 0, 5, 7);
tev_stages_cnt++;
}
}
for(u32 i = 0; i < tev_stages_cnt; i++)
{
GX_SetTevColorOp(GX_TEVSTAGE0 + i, 0, 0, 0, 1, 0);
GX_SetTevAlphaOp(GX_TEVSTAGE0 + i, 0, 0, 0, 1, 0);
GX_SetTevDirect(GX_TEVSTAGE0 + i);
GX_SetTevSwapMode(GX_TEVSTAGE0 + i, 0, 0);
}
}
// enable correct number of tev stages
GX_SetNumTevStages(tev_stages_cnt);
}
inline void Material::ApplyIndStages(void) const
{
for( int i = 0; i < flags->ind_srt; i++ )
{
const IndSrt &ind = ind_srt[i];
const float rotate_rad = DegToRad(ind.rotate);
// maybe add a look up table
float cosF = cosf(rotate_rad);
float sinF = sinf(rotate_rad);
int scale_exp = 0;
f32 mtx23[2][3];
f32 mtxabs23[2][3];
mtx23[0][0] = ind.scale_x * cosF;
mtx23[0][1] = ind.scale_y * -sinF;
mtx23[0][2] = ind.translate_x;
mtx23[1][0] = ind.scale_x * sinF;
mtx23[1][1] = ind.scale_y * cosF;
mtx23[1][2] = ind.translate_y;
// create matrix with abs values
// compiler will optimize the loops
for(int n = 0; n < 2; n++)
for(int m = 0; m < 3; m++)
mtxabs23[n][m] = fabs(mtx23[n][m]);
// hardcore clamping going on here
if( (mtxabs23[0][0] >= 1.0f)
|| (mtxabs23[0][1] >= 1.0f)
|| (mtxabs23[0][2] >= 1.0f)
|| (mtxabs23[1][0] >= 1.0f)
|| (mtxabs23[1][1] >= 1.0f)
|| (mtxabs23[1][2] >= 1.0f))
{
while( scale_exp < 0x2E
&& ((mtxabs23[0][0] >= 1.0f)
|| (mtxabs23[0][1] >= 1.0f)
|| (mtxabs23[0][2] >= 1.0f)
|| (mtxabs23[1][0] >= 1.0f)
|| (mtxabs23[1][1] >= 1.0f)
|| (mtxabs23[1][2] >= 1.0f)))
{
for(int n = 0; n < 2; n++)
{
for(int m = 0; m < 3; m++)
{
mtx23[n][m] *= 0.5f;
mtxabs23[n][m] *= 0.5f;
}
}
scale_exp++;
}
}
else if( (mtxabs23[0][0] < 0.5f)
&& (mtxabs23[0][1] < 0.5f)
&& (mtxabs23[0][2] < 0.5f)
&& (mtxabs23[1][0] < 0.5f)
&& (mtxabs23[1][1] < 0.5f)
&& (mtxabs23[1][2] < 0.5f))
{
while( scale_exp > -0x11
&& (mtxabs23[0][0] < 0.5f)
&& (mtxabs23[0][1] < 0.5f)
&& (mtxabs23[0][2] < 0.5f)
&& (mtxabs23[1][0] < 0.5f)
&& (mtxabs23[1][1] < 0.5f)
&& (mtxabs23[1][2] < 0.5f))
{
for(int n = 0; n < 2; n++)
{
for(int m = 0; m < 3; m++)
{
mtx23[n][m] *= 2.0f;
mtxabs23[n][m] *= 2.0f;
}
}
scale_exp--;
}
}
GX_SetIndTexMatrix(GX_ITM_0 + i, mtx23, scale_exp);
}
for( int i = 0; i < flags->ind_stage; i++ )
{
const IndStage &stage = ind_stage[i];
GX_SetIndTexOrder(i, stage.texcoord, stage.tex_map);
GX_SetIndTexCoordScale(i, stage.scale_s, stage.scale_t);
}
GX_SetNumIndStages(flags->ind_stage);
}
inline void Material::ApplyTextures(const BannerResources& resources) const
{
u8 tlut_name = 0;
for(u32 i = 0; i < flags->texture_map; ++i)
{
const TextureMap &tr = texture_maps[i];
if(palette_texture[i] == DEFAULT_PALETTE)
{
if (tr.tex_index < resources.textures.size())
resources.textures[tr.tex_index]->Apply(tlut_name, i, tr.wrap_s, tr.wrap_t);
}
else
{
// find texture from palette
if(palette_texture[i] >= resources.palettes[resources.cur_set].size())
{
gprintf( "palette index is out of range %i\n", palette_texture[i]);
return;
}
for(u32 n = 0; n < resources.textures.size(); n++)
{
if(resources.textures[n]->getName() == resources.palettes[resources.cur_set][palette_texture[i]])
{
resources.textures[n]->Apply(tlut_name, i, tr.wrap_s, tr.wrap_t);
break;
}
}
}
}
// invalidate texture cache
GX_InvalidateTexAll();
}
void Material::Apply(const BannerResources& resources, u8 render_alpha, bool modulate_colors) const
{
// channel control and material color
ApplyChannelControl(render_alpha, modulate_colors);
// texture coordinates gen
ApplyTexCoordGens();
// bind textures
ApplyTextures(resources);
for (u32 i = 0; i < 4; ++i)
{
// tev reg colors
if(i < 3)
GX_SetTevColorS10(GX_TEVREG0 + i, header->color_regs[i]);
// tev k colors
GX_SetTevKColor(GX_KCOLOR0 + i, header->color_constants[i]);
}
// tev swap colors
ApplyTevSwapTable();
// tev stages
ApplyTevStages(modulate_colors);
// ind stages
ApplyIndStages();
// alpha compare
if(flags->alpha_compare)
GX_SetAlphaCompare(alpha_compare->compare & 0xf, alpha_compare->ref0,
alpha_compare->op, alpha_compare->compare >> 4, alpha_compare->ref1);
else
GX_SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0);
// blend mode
if (flags->blend_mode)
GX_SetBlendMode(blend_mode->type, blend_mode->src_factor, blend_mode->dst_factor, blend_mode->logical_op);
else
GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_SET);
}
void Material::ProcessHermiteKey(const KeyType& type, float value)
{
if (type.type == ANIMATION_TYPE_TEXTURE_SRT) // texture scale/rotate/translate
{
if (type.target < 5 && type.index < flags->texture_srt)
{
(&texture_srts[type.index].translate_x)[type.target] = value;
return;
}
// TODO: Something is still here: target 0-4 and index 1-9 while texture_srt is 1, value is always 0 or 1
return; // TODO remove this
}
else if (type.type == ANIMATION_TYPE_IND_MATERIAL) // ind texture crap
{
if (type.target < 5 && type.index < flags->ind_srt)
{
(&ind_srt[type.index].translate_x)[type.target] = value;
return;
}
return; // TODO remove this
}
else if (type.type == ANIMATION_TYPE_MATERIAL_COLOR) // material color
{
if (type.target < 4)
{
// mat_color
if(flags->material_color)
(&mat_color->r)[type.target] = FLOAT_2_U8(value);
return;
}
else if (type.target < 0x10)
{
(&header->color_regs->r)[type.target - 4] = FLOAT_2_S16(value);
return;
}
else if (type.target < 0x20)
{
(&header->color_constants->r)[type.target - 0x10] = FLOAT_2_U8(value);
return;
}
}
Base::ProcessHermiteKey(type, value);
}
void Material::ProcessStepKey(const KeyType& type, StepKeyHandler::KeyData data)
{
if (type.type == ANIMATION_TYPE_TEXTURE_PALETTE) // tpl palette
{
if(type.index < MAX_TEX_MAP)
{
palette_texture[type.index] = data.data2;
return;
}
}
Base::ProcessStepKey(type, data);
}

253
source/banner/Material.h Normal file
View File

@ -0,0 +1,253 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - Dimok and giantpune
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef WII_BNR_MATERIAL_H_
#define WII_BNR_MATERIAL_H_
#include "Animator.h"
#include "BannerTexture.hpp"
struct BannerResources;
class Material : public Animator
{
public:
typedef Animator Base;
struct Header
{
char name[20];
GXColorS10 color_regs[3];
GXColor color_constants[4];
u32 flags;
} __attribute__((packed));
Material();
void Load(Material::Header *mat);
void Apply(const BannerResources& resources, u8 render_alpha, bool modulate) const;
const char *getName() const { return header->name; }
const Material::Header *GetHeader() const { return header; }
protected:
void ProcessHermiteKey(const KeyType& type, float value);
void ProcessStepKey(const KeyType& type, StepKeyHandler::KeyData data);
private:
void ApplyChannelControl(u8 render_alpha, bool &modulate_colors) const;
void ApplyTevSwapTable(void) const;
void ApplyTexCoordGens(void) const;
void ApplyTevStages(bool modulate_colors) const;
void ApplyIndStages(void) const;
void ApplyTextures(const BannerResources& resources) const;
enum
{
MAX_TEX_MAP = 8,
MAX_TEX_SRT = 10,
MAX_TEX_GEN = 8,
MAX_IND_STAGES = 4,
MAX_TEV_STAGES = 16,
DEFAULT_PALETTE = 0xFF,
};
struct MatFlags
{
u32 pad2 : 4;
u32 material_color : 1;
u32 pad : 1;
u32 channel_control : 1;
u32 blend_mode : 1;
u32 alpha_compare : 1;
u32 tev_stages : 5;
u32 ind_stage : 3;
u32 ind_srt : 2;
u32 tev_swap_table : 1;
u32 texture_coord_gen : 4;
u32 texture_srt : 4;
u32 texture_map : 4;
} __attribute__((packed));
struct TextureMap
{
u16 tex_index;
u8 wrap_s;
u8 wrap_t;
} __attribute__((packed));
struct TextureSrt
{
f32 translate_x;
f32 translate_y;
f32 rotate;
f32 scale_x;
f32 scale_y;
} __attribute__((packed));
struct TextureCoordGen
{
u8 tgen_typ;
u8 tgen_src;
u8 mtxsrc;
u8 pad;
} __attribute__((packed));
struct ChannelControl
{
u8 color_matsrc;
u8 alpha_matsrc;
u16 pad;
} __attribute__((packed));
struct IndSrt
{
f32 translate_x;
f32 translate_y;
f32 rotate;
f32 scale_x;
f32 scale_y;
} __attribute__((packed));
struct IndStage
{
u8 texcoord;
u8 tex_map;
u8 scale_s;
u8 scale_t;
} __attribute__((packed));
struct BlendModes
{
u8 type, src_factor, dst_factor, logical_op;
} __attribute__((packed));
struct AlphaCompareModes
{
u8 compare, op, ref0, ref1;
} __attribute__((packed));
struct TevSwap
{
u32 a : 2;
u32 b : 2;
u32 g : 2;
u32 r : 2;
} __attribute__((packed));
struct TevStage
{
u32 texcoord : 8;
u32 color : 8;
u32 tex_map : 8;
u32 unk : 3;
u32 tex_sel : 2;
u32 ras_sel : 2;
u32 lowBit : 1;
struct
{
u32 b : 4;
u32 a : 4;
u32 d : 4;
u32 c : 4;
u32 tevscale : 2;
u32 tevbias : 2;
u32 tevop : 4;
u32 sel : 5;
u32 tevregid : 2;
u32 clamp : 1;
} __attribute__((packed)) color_in, __attribute__((packed)) alpha_in;
struct
{
u32 unk1 : 6;
u32 indtexid : 2;
u32 unk2 : 1;
u32 mtxid : 4;
u32 bias : 3;
u32 unk3 : 2;
u32 wrap_t : 3;
u32 wrap_s : 3;
u32 unk4 : 2;
u32 a : 2;
u32 utclod : 1;
u32 addprev : 1;
u32 format : 2;
} __attribute__((packed)) ind;
} __attribute__((packed));
// Material flags
MatFlags *flags;
// Texture
TextureMap *texture_maps;
TextureSrt *texture_srts;
TextureCoordGen *texture_coord_gens;
// Color channels
ChannelControl *chan_control;
// Material colors
GXColor *mat_color;
// Tev color swap
TevSwap *tev_swap_table;
// Indirect textures
IndSrt *ind_srt;
IndStage *ind_stage;
// Texture environment
TevStage *tev_stages;
// Blending and alpha compare
AlphaCompareModes *alpha_compare;
BlendModes *blend_mode;
// palette animation
u8 palette_texture[MAX_TEX_MAP];
//! Material header
Material::Header *header;
};
class MaterialList : public std::vector<Material*>
{
public:
static const u32 MAGIC = MAKE_FOURCC('m', 'a', 't', '1');
};
#endif

165
source/banner/Pane.cpp Normal file
View File

@ -0,0 +1,165 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - Dimok
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Pane.h"
#include "Layout.h"
void Pane::Load(Pane::Header *pan)
{
if(!pan)
return;
header = pan;
hide = false;
RootPane = !strcmp( header->name, "RootPane" );
AlignHor = header->origin % 3;
AlignVer = 2 - header->origin / 3;
}
Pane::~Pane()
{
// delete children
for(u32 i = 0; i < panes.size(); ++i)
delete panes[i];
}
void Pane::SetFrame(FrameNumber frame, u8 key_set)
{
// setframe on self
Animator::SetFrame(frame, key_set);
// setframe on children
for(u32 i = 0; i < panes.size(); ++i)
panes[i]->SetFrame(frame, key_set);
}
void Pane::Render(const BannerResources& resources, u8 parent_alpha, Mtx &modelview,
bool widescreen, bool modify_alpha) const
{
if (!header || !GetVisible() || GetHide())
return;
u8 render_alpha = header->alpha;
if(RootPane && parent_alpha != 0xFF)
{
modify_alpha = true;
render_alpha = MultiplyAlpha(header->alpha, parent_alpha);
}
if(!RootPane && modify_alpha)
{
render_alpha = MultiplyAlpha(header->alpha, parent_alpha);
}
else if(GetInfluencedAlpha() && header->alpha != 0xff)
{
modify_alpha = true;
parent_alpha = MultiplyAlpha(header->alpha, parent_alpha);
}
float ws_scale = 1.0f;
if(widescreen && GetWidescren())
{
ws_scale *= 0.82f; // should actually be 0.75?
widescreen = false;
}
Mtx m1,m2,m3,m4, mv;
guMtxIdentity (m1);
// Scale
guMtxScaleApply(m1,m1, header->scale.x * ws_scale, header->scale.y, 1.f);
// Rotate
guMtxRotDeg ( m2, 'x', header->rotate.x );
guMtxRotDeg ( m3, 'y', header->rotate.y );
guMtxRotDeg ( m4, 'z', header->rotate.z );
guMtxConcat(m2, m3, m2);
guMtxConcat(m2, m4, m2);
guMtxConcat(m1, m2, m1);
// Translate
guMtxTransApply(m1,m1, header->translate.x, header->translate.y, header->translate.z);
guMtxConcat (modelview, m1, mv);
// render self
Draw(resources, render_alpha, ws_scale, mv);
// render children
for(u32 i = 0; i < panes.size(); ++i)
panes[i]->Render(resources, render_alpha, mv, widescreen, modify_alpha);
}
Pane* Pane::FindPane(const std::string& find_name)
{
if(!header)
return NULL;
if (find_name.compare(0, 0x10, getName()) == 0)
return this;
for(u32 i = 0; i < panes.size(); ++i)
{
Pane *found = panes[i]->FindPane(find_name);
if (found)
return found;
}
return NULL;
}
void Pane::ProcessHermiteKey(const KeyType& type, float value)
{
if (type.type == ANIMATION_TYPE_VERTEX_COLOR) // vertex color
{
// only alpha is supported for Panes afaict
if (0x10 == type.target)
{
header->alpha = FLOAT_2_U8(value);
return;
}
}
else if (type.type == ANIMATION_TYPE_PANE) // pane animation
{
if (type.target < 10)
{
(&header->translate.x)[type.target] = value;
return;
}
}
Base::ProcessHermiteKey(type, value);
}
void Pane::ProcessStepKey(const KeyType& type, StepKeyHandler::KeyData data)
{
if (type.type == ANIMATION_TYPE_VISIBILITY) // visibility
{
SetVisible(!!data.data2);
return;
}
Base::ProcessStepKey(type, data);
}

143
source/banner/Pane.h Normal file
View File

@ -0,0 +1,143 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - Dimok
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef WII_BNR_PANE_H_
#define WII_BNR_PANE_H_
#include <vector>
#include <gccore.h>
#include "Animator.h"
struct BannerResources;
class Pane;
typedef std::vector<Pane*> PaneList;
class Pane : public Animator
{
public:
typedef Animator Base;
static const u32 MAGIC = MAKE_FOURCC('p', 'a', 'n', '1');
struct Header
{
u32 magic;
u32 size_section;
u8 flags;
u8 origin;
u8 alpha;
u8 padding;
char name [0x10];
char user_data [0x08];
Vec3f translate;
Vec3f rotate;
Vec2f scale;
float width;
float height;
} __attribute__((packed));
Pane() : header(NULL) {}
virtual ~Pane();
void Load(Pane::Header *file);
const char *getName() const { if(!header) return ""; return header->name; }
void Render(const BannerResources& resources, u8 parent_alpha, Mtx &modelview,
bool widescreen, bool modify_alpha = false) const;
void SetFrame(FrameNumber frame, u8 key_set);
void SetScale(float scale) { if(header) header->scale.x = header->scale.y = scale; }
bool GetHide() const { return hide; }
void SetHide(bool _hide) { hide = _hide; }
bool GetVisible() const { if(!header) return false; return ((header->flags & (1 << FLAG_VISIBLE)) != 0); }
void SetVisible(bool visible)
{
if(!header)
return;
if(visible)
header->flags |= (1 << FLAG_VISIBLE);
else
header->flags &= ~(1 << FLAG_VISIBLE);
}
u8 GetOriginX() const { return AlignHor; }
u8 GetOriginY() const { return AlignVer; }
float GetWidth() const { if(!header) return 0.f; return header->width; }
float GetHeight() const { if(!header) return 0.f; return header->height; }
bool GetInfluencedAlpha() const { if(!header) return false; return ((header->flags & (1 << FLAG_INFLUENCED_ALPHA)) != 0); }
void SetInfluencedAlpha(bool influenced)
{
if(!header)
return;
if(influenced)
header->flags |= (1 << FLAG_INFLUENCED_ALPHA);
else
header->flags &= ~(1 << FLAG_INFLUENCED_ALPHA);
}
bool GetWidescren() const { return ((header->flags & (1 << FLAG_WIDESCREEN)) != 0); }
Pane* FindPane(const std::string& name); // recursive
PaneList panes;
protected:
void ProcessHermiteKey(const KeyType& type, float value);
void ProcessStepKey(const KeyType& type, StepKeyHandler::KeyData data);
private:
virtual void Draw(const BannerResources&, u8, const float, Mtx&) const {}
enum
{
FLAG_VISIBLE = 0x00,
FLAG_INFLUENCED_ALPHA = 0x01,
FLAG_WIDESCREEN = 0x02
};
Pane::Header *header;
bool hide; // used by the groups
bool RootPane;
u8 AlignVer;
u8 AlignHor;
};
// apparently Bounding is just a regular pane
class Bounding : public Pane
{
public:
static const u32 MAGIC = MAKE_FOURCC('b', 'n', 'd', '1');
};
#endif

34
source/banner/Picture.cpp Normal file
View File

@ -0,0 +1,34 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - Dimok
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Picture.h"
void Picture::Load(Pane::Header * file)
{
if(!file)
return;
Pane::Load(file);
QuadPane::Load((QuadPane::Header *) (file+1));
}

40
source/banner/Picture.h Normal file
View File

@ -0,0 +1,40 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - Dimok
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef WII_BNR_PICTURE_H_
#define WII_BNR_PICTURE_H_
#include "QuadPane.h"
class Picture : public QuadPane
{
public:
typedef QuadPane Base;
static const u32 MAGIC = MAKE_FOURCC('p', 'i', 'c', '1');
void Load(Pane::Header *hdr);
};
#endif

126
source/banner/QuadPane.cpp Normal file
View File

@ -0,0 +1,126 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - Dimok
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "QuadPane.h"
#include "Layout.h"
void QuadPane::Load(QuadPane::Header* file)
{
if(!file)
return;
header = file;
tex_coords = (const TexCoords *) (header+1);
}
inline void QuadPane::SetVertex(int ind, float x, float y, u8 render_alpha) const
{
// position
GX_Position3f32(x, y, 0.f);
const GXColor &vertex_color = header->vertex_colors[ind];
// color
GX_Color4u8(vertex_color.r, vertex_color.g, vertex_color.b,
MultiplyAlpha(vertex_color.a, render_alpha));
// texture coord
for(u32 i = 0; i < header->tex_coord_count; i++)
GX_TexCoord2f32(tex_coords[i].coords[ind].s, tex_coords[i].coords[ind].t);
}
static inline bool IsModulateColor(GXColor *colors, u8 render_alpha)
{
if(render_alpha != 0xFF)
return true;
u32 *colorPtr = (u32 *) colors;
for(int i = 0; i < 4; ++i)
{
if(colorPtr[i] != 0xFFFFFFFF)
return true;
}
return false;
}
void QuadPane::Draw(const BannerResources& resources, u8 render_alpha, const float ws_scale, Mtx &modelview, u16 material_index, u8 texture_flip) const
{
if(!header)
return;
if (material_index < resources.materials.size())
{
bool modulate_color = IsModulateColor(header->vertex_colors, render_alpha);
resources.materials[material_index]->Apply(resources, render_alpha, modulate_color);
}
Mtx m, mv;
guMtxIdentity (m);
guMtxTransApply(m,m, -0.5f * GetOriginX(), -0.5f * GetOriginY(), 0.f);
guMtxScaleApply(m,m, GetWidth(), GetHeight(), 1.f);
guMtxConcat (modelview, m, mv);
GX_LoadPosMtxImm (mv, GX_PNMTX0);
GX_ClearVtxDesc();
GX_InvVtxCache();
GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT);
for(u32 i = 0; i < header->tex_coord_count; i++)
GX_SetVtxDesc(GX_VA_TEX0+i, GX_DIRECT);
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
if(texture_flip)
{
SetVertex(0, 0.f, 0.f, render_alpha);
SetVertex(1, 1.f, 0.f, render_alpha);
SetVertex(3, 1.f, 1.f, render_alpha);
SetVertex(2, 0.f, 1.f, render_alpha);
}
else
{
SetVertex(2, 0.f, 0.f, render_alpha);
SetVertex(3, 1.f, 0.f, render_alpha);
SetVertex(1, 1.f, 1.f, render_alpha);
SetVertex(0, 0.f, 1.f, render_alpha);
}
GX_End();
}
void QuadPane::ProcessHermiteKey(const KeyType& type, float value)
{
if (type.type == ANIMATION_TYPE_VERTEX_COLOR) // vertex color
{
if (type.target < 0x10)
{
// vertex colors
(&header->vertex_colors->r)[type.target] = FLOAT_2_U8(value);
return;
}
}
Base::ProcessHermiteKey(type, value);
}

73
source/banner/QuadPane.h Normal file
View File

@ -0,0 +1,73 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - Dimok
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef _QUAD_PANE_H_
#define _QUAD_PANE_H_
#include "Pane.h"
// used by Picture and Window
class QuadPane : public Pane
{
public:
typedef Pane Base;
struct Header
{
GXColor vertex_colors[4];
u16 material_index;
u8 tex_coord_count;
u8 pad;
} __attribute__((packed));
QuadPane() : header(NULL) {}
void Load(QuadPane::Header *file);
protected:
void ProcessHermiteKey(const KeyType& type, float value);
//! overload
void Draw(const BannerResources& resources, u8 render_alpha, const float ws_scale, Mtx &view,
u16 material_index, u8 texture_flip) const;
//! main virtual draw function
void Draw(const BannerResources& resources, u8 render_alpha, const float ws_scale, Mtx &view) const {
Draw(resources, render_alpha, ws_scale, view, header->material_index, 0);
}
private:
void SetVertex(int ind, float x, float y, u8 render_alpha) const;
struct TexCoords
{
struct TexCoord
{
float s;
float t;
} coords[4];
};
QuadPane::Header *header;
const TexCoords *tex_coords;
};
#endif

280
source/banner/Textbox.cpp Normal file
View File

@ -0,0 +1,280 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - giantpune
Copyright (c) 2012 - Dimok
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Textbox.h"
#include "Layout.h"
void Textbox::Load(Pane::Header *file)
{
if(!file)
return;
Pane::Load(file);
header = (Textbox::Header *) (file + 1);
text = (const u16 *) (header + 1);
textAlignVer = (header->text_alignment / 3);
textAlignHor = (header->text_alignment % 3);
}
void Textbox::SetTextWidth(WiiFont *font)
{
lineWidths.clear();
frameWidth = 0.f;
frameHeight = header->font_size;
float currentLine = 0.f;
float scale = header->font_size /(float)font->CharacterHeight();
for(const u16 *txtString = text; *txtString != 0; txtString++)
{
if(*txtString == '\n')
{
currentLine *= scale;
lineWidths.push_back(currentLine);
frameWidth = MAX(frameWidth, currentLine);
frameHeight += header->font_size + header->space_line;
currentLine = 0.f;
continue;
}
const WiiFont::CharInfo *charInfo = font->GetCharInfo(*txtString);
if(!charInfo)
continue;
if(charInfo->unk)
currentLine += (float) charInfo->advanceKerning;
currentLine += (float) charInfo->advanceGlyphX;
}
currentLine *= scale;
lineWidths.push_back(currentLine);
frameWidth = MAX(frameWidth, currentLine);
}
void Textbox::SetupGX(const BannerResources& resources) const
{
GX_ClearVtxDesc();
GX_InvVtxCache();
GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT);
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
// channel control
GX_SetNumChans(1);
GX_SetChanCtrl(GX_COLOR0A0,GX_DISABLE,GX_SRC_REG,GX_SRC_VTX,GX_LIGHTNULL,GX_DF_NONE,GX_AF_NONE);
// texture gen.
GX_SetNumTexGens(1);
GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
// texture environment
GX_SetNumTevStages(1);
GX_SetNumIndStages(0);
GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE);
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
GX_SetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0);
GX_SetTevKColorSel(GX_TEVSTAGE0, GX_TEV_KCSEL_1_4);
GX_SetTevKAlphaSel(GX_TEVSTAGE0, GX_TEV_KASEL_1);
GX_SetTevDirect(GX_TEVSTAGE0);
// swap table
GX_SetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA);
GX_SetTevSwapModeTable(GX_TEV_SWAP1, GX_CH_RED, GX_CH_RED, GX_CH_RED, GX_CH_ALPHA);
GX_SetTevSwapModeTable(GX_TEV_SWAP2, GX_CH_GREEN, GX_CH_GREEN, GX_CH_GREEN, GX_CH_ALPHA);
GX_SetTevSwapModeTable(GX_TEV_SWAP3, GX_CH_BLUE, GX_CH_BLUE, GX_CH_BLUE, GX_CH_ALPHA);
// alpha compare and blend mode
GX_SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0);
GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_SET);
if(header->material_index < resources.materials.size())
{
const Material::Header *matHead = resources.materials[header->material_index]->GetHeader();
if(!matHead)
return;
//GX_SetFog(0, 0.0f, 0.0f, 0.0f, 0.0f, (GXColor){0xff, 0xff, 0xff, 0xff});
GX_SetTevSwapModeTable(0, 0, 1, 2, 3);
//GX_SetZTexture(0, 0x11, 0);
GX_SetNumChans(1 );
GX_SetChanCtrl(4, 0, 0, 1, 0, 0, 2);
GX_SetChanCtrl(5, 0, 0, 0, 0, 0, 2);
GX_SetNumTexGens(1);
GX_SetTexCoordGen2(0, 1, 4, 0x3c, 0, 0x7D);
GX_SetNumIndStages(0);
GX_SetBlendMode(1, 4, 5, 0xf);
GX_SetNumTevStages(2);
GX_SetTevDirect(0);
GX_SetTevDirect(1);
GX_SetTevSwapMode(0, 0, 0);
GX_SetTevSwapMode(1, 0, 0);
GX_SetTevOrder(0, 0, 0, 0xff);
for( int i = 0; i < 2; i++ )
{
GX_SetTevColor(i + 1, (GXColor){ LIMIT(matHead->color_regs[i].r, 0, 0xFF),
LIMIT(matHead->color_regs[i].g, 0, 0xFF),
LIMIT(matHead->color_regs[i].b, 0, 0xFF),
LIMIT(matHead->color_regs[i].a, 0, 0xFF) });
}
GX_SetTevColorIn(0, 2, 4, 8, 0xf);
GX_SetTevAlphaIn(0, 1, 2, 4, 7);
GX_SetTevColorOp(0, 0, 0, 0, 1, 0);
GX_SetTevAlphaOp(0, 0, 0, 0, 1, 0);
GX_SetTevOrder(1, 0xff, 0xff, 4);
GX_SetTevColorIn(1, 0xf, 0, 0xa, 0xf);
GX_SetTevAlphaIn(1, 7, 0, 5, 7);
GX_SetTevColorOp(1, 0, 0, 0, 1, 0);
GX_SetTevAlphaOp(1, 0, 0, 0, 1, 0);
}
}
void Textbox::Draw(const BannerResources& resources, u8 parent_alpha, const float ws_scale, Mtx &modelview) const
{
if(!text)
return;
if(header->font_index >= resources.fonts.size())
return;
WiiFont *font = resources.fonts[header->font_index];
if(!font->IsLoaded())
return;
// Ugly...but doing it by going through all panes is more ugly
// TODO: move it to somewhere else
if(lineWidths.empty())
((Textbox *) this)->SetTextWidth(font);
if(lineWidths.empty())
return;
SetupGX(resources);
GX_LoadPosMtxImm(modelview, GX_PNMTX0);
// Setup text color
GXColor color0 = { header->color[0].r,
header->color[0].g,
header->color[0].b,
MultiplyAlpha(header->color[0].a, parent_alpha) };
GXColor color1 = { header->color[1].r,
header->color[1].g,
header->color[1].b,
MultiplyAlpha(header->color[1].a, parent_alpha) };
u32 lastSheetIdx = 0xffff;
float scale = header->font_size /(float)font->CharacterHeight();
// use complete text width if not aligned to middle
float textWidth = (GetAlignHor() == 1) ? lineWidths[0] : frameWidth;
// position offset calculation for first line...why the hell is it that complex?
float xPos = -0.5f * ( GetOriginX() * GetWidth() * ws_scale +
GetAlignHor() * (-GetWidth() * ws_scale + textWidth) );
float yPos = -0.5f * ( GetAlignVer() * -frameHeight +
GetHeight() * (GetAlignVer() - (2 - GetOriginY())) )
- header->font_size;
// store the character width here for later use, it's constant over the text
float charWidth = scale * (float)font->CharacterWidth();
int lineNumber = 0;
for(const u16 *txtString = text; *txtString != 0; txtString++)
{
if(*txtString == '\n')
{
lineNumber++;
// use complete text width if not aligned to middle
textWidth = (GetAlignHor() == 1) ? lineWidths[lineNumber] : frameWidth;
// calculate text position depending on line width
xPos = -0.5f * (GetOriginX() * GetWidth() * ws_scale +
GetAlignHor() * (-GetWidth() * ws_scale + textWidth));
// go one line down
yPos -= (header->font_size + header->space_line);
continue;
}
const WiiFont::CharInfo *charInfo = font->GetCharInfo(*txtString);
if(!charInfo)
continue;
if(charInfo->sheetIdx != lastSheetIdx)
{
lastSheetIdx = charInfo->sheetIdx;
if(!font->Apply(charInfo->sheetIdx))
continue;
}
if(charInfo->unk)
xPos += scale * (float)charInfo->advanceKerning;
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
GX_Position3f32(xPos, yPos, 0.f);
GX_Color4u8(color1.r, color1.g, color1.b, color1.a);
GX_TexCoord2f32(charInfo->s1, charInfo->t2);
GX_Position3f32(xPos + charWidth, yPos, 0.f);
GX_Color4u8(color1.r, color1.g, color1.b, color1.a);
GX_TexCoord2f32(charInfo->s2, charInfo->t2);
GX_Position3f32(xPos + charWidth, yPos + header->font_size, 0.f);
GX_Color4u8(color0.r, color0.g, color0.b, color0.a);
GX_TexCoord2f32(charInfo->s2, charInfo->t1);
GX_Position3f32(xPos, yPos + header->font_size, 0.f);
GX_Color4u8(color0.r, color0.g, color0.b, color0.a);
GX_TexCoord2f32(charInfo->s1, charInfo->t1);
GX_End();
xPos += scale * (float)charInfo->advanceGlyphX;
}
}
void Textbox::ProcessHermiteKey(const KeyType& type, float value)
{
if (type.type == ANIMATION_TYPE_VERTEX_COLOR) // vertex color
{
if(type.target < 4)
{
(&header->color[0].r)[type.target] = FLOAT_2_U8(value);
return;
}
else if(type.target >= 8 && type.target < 12)
{
(&header->color[1].r)[type.target - 8] = FLOAT_2_U8(value);
return;
}
}
Base::ProcessHermiteKey(type, value);
}
void Textbox::ProcessStepKey(const KeyType& type, StepKeyHandler::KeyData data)
{
Base::ProcessStepKey(type, data);
}

85
source/banner/Textbox.h Normal file
View File

@ -0,0 +1,85 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - giantpune
Copyright (c) 2012 - Dimok
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef WII_BNR_TEXTBOX_H_
#define WII_BNR_TEXTBOX_H_
#include "Pane.h"
class WiiFont;
class Textbox : public Pane
{
public:
typedef Pane Base;
Textbox() : header(NULL), text(NULL), frameWidth(0.f), frameHeight(0.f)
{ }
static const u32 MAGIC = MAKE_FOURCC('t', 'x', 't', '1');
void Load(Pane::Header *file);
u8 GetAlignHor() const { return textAlignHor; }
u8 GetAlignVer() const { return textAlignVer; }
void SetText(const u16 *t) { text = t; lineWidths.clear(); }
protected:
void ProcessHermiteKey(const KeyType& type, float value);
void ProcessStepKey(const KeyType& type, StepKeyHandler::KeyData data);
private:
void Draw(const BannerResources& resources, u8 render_alpha, const float ws_scale, Mtx &view) const;
void SetupGX(const BannerResources& resources) const;
void SetTextWidth(WiiFont *font);
struct Header
{
u16 text_buf_bytes;
u16 text_str_bytes;
u16 material_index;
u16 font_index;
u8 text_alignment;
u8 pad1; // ?
u8 pad2[2];
u32 text_str_offset;
GXColor color[2];
float font_size;
float height; // seems to work better for offset calculation
float space_char;
float space_line;
} __attribute__((packed));
Textbox::Header *header;
const u16 *text;
float frameWidth;
float frameHeight;
u8 textAlignVer;
u8 textAlignHor;
std::vector<float> lineWidths;
};
#endif

387
source/banner/WiiFont.cpp Normal file
View File

@ -0,0 +1,387 @@
/*
Copyright (c) 2012 - giantpune
Copyright (c) 2012 - Dimok
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include <malloc.h>
#include "WiiFont.h"
WiiFont::WiiFont()
: header(NULL)
, finf(NULL)
, tglp(NULL)
, cwdh(NULL)
, font_loaded(false)
{
}
WiiFont::~WiiFont()
{
std::map<u16, TextureCache>::iterator itr;
for (itr = textureMap.begin(); itr != textureMap.end(); itr++)
{
if(itr->second.allocated && itr->second.texture_data)
free(itr->second.texture_data);
}
}
bool WiiFont::Load(const u8 *file)
{
if(!file)
return false;
header = (WiiFont::Header *) file;
if((header->magic != MAGIC_FONT && header->magic != MAGIC_FONT_ARCHIVE)
|| header->version != MAGIC_VERSION)
{
header = NULL;
return false;
}
const u8 *position = ((const u8 *)header) + header->header_len;
for(u32 i = 0; i < header->section_count; ++i)
{
section_t *section = (section_t *) position;
position += section->size;
switch( section->magic )
{
case MAGIC_GLYPH_GROUP:
glgr = (GlgrHeader *) section;
break;
case MAGIC_FONT_INFORMATION:
finf = (FinfHeader *) section;
break;
case MAGIC_TEXTURE_GLYPH:
tglp = (TglpHeader *) section;
break;
case MAGIC_CHARACTER_WIDTH:
cwdh = (CwdhHeader *) section;
break;
case MAGIC_CHARACTER_CODE_MAP:
ParseCmap((CmapEntry *) (section + 1));
break;
default:
// ignore
gprintf("Uknown section %.4s\n", (char *) &section->magic);
break;
}
}
// Some sanity checks
if(!finf || !tglp || !cwdh)
return false;
if(finf->tglpOffset > header->filesize || finf->cwdhOffset > header->filesize
|| finf->cmapOffset > header->filesize)
return false;
font_loaded = true;
return true;
}
inline bool WiiFont::CheckCmap(u16 charCode, u16 mapValue)
{
std::map<u16, u16>::iterator it = cmap.find(charCode);
if(it != cmap.end())
{
if((*it).second != mapValue)
{
gprintf("Duplicate characters\n");
return false;
}
}
return true;
}
bool WiiFont::ParseCmap(CmapEntry *cmapEntry)
{
if(!cmapEntry)
return false;
while(true)
{
switch(cmapEntry->type)
{
case 0:
{
for(u16 i = cmapEntry->charCode, j = cmapEntry->start; j < cmapEntry->end; j++, i++)
{
if(!CheckCmap(j, i))
return false;
cmap[j] = i;
}
break;
}
case 1:
{
u16 idx = 0;
u16 *idxPointer = &cmapEntry->charCode;
for(u32 i = cmapEntry->start; i < cmapEntry->end; i++)
{
u16 m_idx = idxPointer[idx++];
if(m_idx == 0xffff)
continue;
if(!CheckCmap(i, m_idx))
return false;
cmap[i] = m_idx;
}
break;
}
case 2:
{
u16 ind, character;
u16 *charData = (u16 *) (cmapEntry + 1);
for(u32 i = 0; i < cmapEntry->charCode; i++)
{
character = charData[0];
ind = charData[1];
charData += 2;
if(!CheckCmap(character, ind))
return false;
cmap[character] = ind;
}
break;
}
default:
gprintf( "unknown cmap type\n" );
return false;
}
if(cmapEntry->pos == 0)
return true;
cmapEntry = (CmapEntry *)(((u8 *)header) + cmapEntry->pos);
}
}
const WiiFont::CharInfo *WiiFont::GetCharInfo(u16 charCode)
{
if(!finf || !tglp || !cwdh)
return NULL;
// see if the character already exists in our cache
std::map<u16, CharInfo>::iterator itr = charInfoMap.find(charCode);
if(itr != charInfoMap.end())
return &itr->second;
u16 idx = CharToIdx(charCode);
if(idx > cwdh->endIdx)
{
gprintf( "idx > cwdh->endIdx" );
return NULL;
}
Cwdh *cwdh2 = (Cwdh*) (((u8 *)header) + finf->cwdhOffset + 8);
u32 chars_per_texture = (tglp->charColumns * tglp->charRows);
u32 tex_idx = idx / chars_per_texture;
u32 row = (idx - chars_per_texture * tex_idx) / tglp->charColumns;
u32 col = (idx - chars_per_texture * tex_idx) - ( tglp->charColumns * row );
f32 _s1 = ((tglp->cellWidth + 1) * col) / (f32)tglp->width;
f32 _s2 = _s1 + CharacterWidth() / (f32)tglp->width;
// this is good vertically but horizontal without it it looks clearer
f32 _t1 = ((tglp->cellHeight + 1) * row + 0.5f * (CharacterHeight() - (tglp->cellHeight + 1))) / (f32)tglp->height;
f32 _t2 = _t1 + CharacterHeight() / (f32)tglp->height;
CharInfo charInfo;
charInfo.sheetIdx = tex_idx;
charInfo.s1 = _s1;
charInfo.s2 = _s2;
charInfo.t1 = _t1;
charInfo.t2 = _t2;
charInfo.advanceGlyphX = cwdh2[idx].advanceGlyphX;
charInfo.unk = cwdh2[idx].unk;
charInfo.advanceKerning = cwdh2[idx].advanceKerning;
charInfoMap[charCode] = charInfo;
return &charInfoMap[charCode];
}
GXTexObj *WiiFont::LoadTextureObj(u16 tex_idx)
{
if(!font_loaded || tex_idx >= tglp->texCnt)
return NULL;
// init texture and add it to the list
TextureCache chacheStruct;
if(header->magic == MAGIC_FONT_ARCHIVE)
{
chacheStruct.texture_data = GetUnpackedTexture(tex_idx);
chacheStruct.allocated = true;
}
else
{
chacheStruct.texture_data = ((u8 *) header) + tglp->dataOffset + tex_idx * tglp->texSize;
chacheStruct.allocated = false;
}
if(!chacheStruct.texture_data)
return NULL;
GX_InitTexObj( &chacheStruct.texObj, chacheStruct.texture_data, tglp->width, tglp->height, 0, 0, 0, true );
GX_InitTexObjLOD( &chacheStruct.texObj, GX_LINEAR,GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_DISABLE, GX_FALSE, GX_ANISO_1 );
textureMap[tex_idx] = chacheStruct;
return &textureMap[tex_idx].texObj;
}
bool WiiFont::Apply(u16 tex_indx)
{
if(!font_loaded)
return false;
if(tex_indx >= tglp->texCnt)
return false;
GXTexObj *tex_obj;
// Load character texture from cache if available otherwise create cache
std::map<u16, TextureCache>::iterator itr = textureMap.find(tex_indx);
if(itr != textureMap.end())
tex_obj = &itr->second.texObj;
else
tex_obj = LoadTextureObj(tex_indx);
// no texture for this character found
if(!tex_obj)
return false;
GX_LoadTexObj(tex_obj, GX_TEXMAP0);
GX_InvalidateTexAll();
return true;
}
// giantpunes little magic function
bool WiiFont::Decompress_0x28( unsigned char *outBuf, u32 outLen, const unsigned char *inBuf, u32 inLen )
{
if( outLen & 3 )// this copies 32 bits at a time, so it probably needs to be aligned
{
gprintf( "length not aligned to 32 bits\n" );
return false;
}
const u32 root_offset = 5;
u32 symbol = 0;
u32 counter = 0;
u32 inIdx = 0;
u32 outIdx = 0;
u32 *in32 = (u32*)( ( inBuf + 6 ) + ( ( inBuf[ 4 ] << 1 ) ) );
u32 *out32 = (u32*)outBuf;
u8 *p = (u8*)inBuf + root_offset;
outLen >>= 2; //we are copying 4 bytes at a time
while( outLen )
{
for( u32 i = 0, leaf = p[ 0 ], bits = __builtin_bswap32( in32[ inIdx ] )
; i < 0x20 && outLen
; i++, leaf = p[ 0 ], bits <<= 1 )
{
u32 topBit = bits >> 31;
u8 d = 2 - ((u64)p & 1);
p += topBit + ( ( leaf << 1 ) & 0x7e ) + d;
if( !( p > (u8*)inBuf ) && ( p < (u8*)inBuf + inLen ) )
{
gprintf( "out of range 1\n" );
return false;
}
if( ( ( leaf << ( topBit ) ) & ( 1 << 7 ) ) ) // p->isLeaf
{
symbol = ( ( p[ 0 ] << 0x18 ) | ( symbol >> 8 ) );
p = (u8*)inBuf + root_offset; // p = root
if( counter++ > 2 )
{
out32[ outIdx++ ] = __builtin_bswap32( symbol );// buf[bufcur++] = p->symbol
counter = 0; // reset counter
outLen--; // decrease amount to copy
}
}
}
if( inIdx++ >= ( inLen >> 2 ) )
{
gprintf( "out of range 2\n" );
return false;
}
}
return true;
}
u8 *WiiFont::GetUnpackedTexture(u16 sheetNo)
{
u8 *data = (u8 *) header;
u32 compressedSize;
u32 off = 0;
// skip over all the sheets till we get the one we want
for( u32 i = 0; i < sheetNo; i++ )
{
compressedSize = *(u32*)( data + tglp->dataOffset + off );
off += compressedSize + 4;
}
compressedSize = *(u32*)( data + tglp->dataOffset + off );
u32 uncompressedSize = *(u32*)( data + tglp->dataOffset + off + 4 );
if( (uncompressedSize & 0xff000000) != 0x28000000 )// looks like all the sheets in wbf1 and wbf2.brfna are 0x28
{
gprintf( "Brfna::LoadSheets(): unknown data type\n" );
return NULL;
}
uncompressedSize = ( __builtin_bswap32( uncompressedSize ) >> 8 );
if( !uncompressedSize )// is this right? it looks like it is. but it SHOULD only happen for files over 0xffffff bytes
{
uncompressedSize = __builtin_bswap32(*(u32*)( data + tglp->dataOffset + off + 8 ));
}
if( uncompressedSize != glgr->sheet_size )
{
gprintf( "uncompressedSize != glgr->sheet_size %08x\n", uncompressedSize );
return NULL;
}
// decompress
u8* sheetData = (u8*)memalign( 32, uncompressedSize );// buffer needs to be 32bit aligned
if( !sheetData )
return NULL;
if( !Decompress_0x28( sheetData, uncompressedSize, ( data + tglp->dataOffset + off + 4 ), compressedSize ) )
{
free( sheetData );
return NULL;
}
// Flush cache
DCFlushRange(sheetData, uncompressedSize);
return sheetData;
}

226
source/banner/WiiFont.h Normal file
View File

@ -0,0 +1,226 @@
/*
Copyright (c) 2012 - giantpune
Copyright (c) 2012 - Dimok
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef __WII_FONT_H_
#define __WII_FONT_H_
#include <list>
#include <vector>
#include "Pane.h"
class WiiFont
{
public:
static const u32 MAGIC_FONT = MAKE_FOURCC('R', 'F', 'N', 'T');
static const u32 MAGIC_FONT_ARCHIVE = MAKE_FOURCC('R', 'F', 'N', 'A');
static const u32 MAGIC_VERSION = 0xFEFF0104;
static const u32 MAGIC_GLYPH_GROUP = MAKE_FOURCC('G', 'L', 'G', 'R');
static const u32 MAGIC_FONT_INFORMATION = MAKE_FOURCC('F', 'I', 'N', 'F');
static const u32 MAGIC_TEXTURE_GLYPH = MAKE_FOURCC('T', 'G', 'L', 'P');
static const u32 MAGIC_CHARACTER_CODE_MAP = MAKE_FOURCC('C', 'M', 'A', 'P');
static const u32 MAGIC_CHARACTER_WIDTH = MAKE_FOURCC('C', 'W', 'D', 'H');
WiiFont();
~WiiFont();
// load the file
bool Load(const u8 *file);
// apply texture, non-const because we load texture on demand
bool Apply(u16 tex_idx);
// struct to hold info for a character to keep from searching and calculating it all every frame
struct CharInfo
{
u32 sheetIdx;
f32 s1;
f32 t1;
f32 s2;
f32 t2;
s8 advanceKerning;
u8 unk;
s8 advanceGlyphX;
};
// get the character information
const CharInfo *GetCharInfo(u16 charCode);
// check if the font was loaded correctly
bool IsLoaded() const { return font_loaded; }
// get some parameters from the FINF header
u8 CharacterWidth() const { return finf ? finf->charWidth : 0; }
u8 CharacterHeight() const { return finf ? finf->height : 0; }
const std::string& getName() const { return name; }
void SetName(const std::string& _name) { name = _name; }
private:
struct Header
{
u32 magic;
u32 version;
u32 filesize;
u16 header_len;
u16 section_count;
} __attribute__((packed));
struct GlgrHeader
{
u32 magic;
u32 sectionSize;
u32 sheet_size;
u16 glyphs_per_sheet;
u16 set_count;
u16 sheet_count;
u16 cwdh_count;
u16 cmap_count;
}__attribute__(( packed ));
struct FinfHeader
{
u32 magic;
u32 headerSize; // finf size
u8 unk8_1; // font type?
u8 leading; //
u16 defaultChar;
u8 leftMargin;
u8 charWidth;
u8 fullWidth;
u8 encoding;
u32 tglpOffset; // TLGP offset
u32 cwdhOffset; // CWDH offset
u32 cmapOffset; // CMAP offset
u8 height;
u8 width;
u8 ascent;
u8 unk8_10;
} __attribute__(( packed ));
struct TglpHeader
{
u32 magic;
u32 tglpSize; // TGLP size
u8 cellWidth; // font width - 1
u8 cellHeight; // font heigh - 1
u8 baselinePos;
u8 maxCharWidth;
u32 texSize; // length of 1 image
u16 texCnt; // number of images
u16 texType; //
u16 charColumns; // character per row
u16 charRows; // characters per column
u16 width; // width of image
u16 height; // height of image
u32 dataOffset; // data offset
} __attribute__(( packed ));
struct CwdhHeader
{
u32 magic;
u32 length; // section length?
u16 startIdx; //
u16 endIdx; //
u32 next; //
} __attribute__(( packed ));
struct CmapEntry
{
u16 start;
u16 end;
u16 type;
u16 pad;
u32 pos;
u16 charCode;
} __attribute__(( packed ));
struct Cwdh
{
s8 advanceKerning;
u8 unk;
s8 advanceGlyphX;
} __attribute__(( packed ));
// font texture decompress functions
static bool Decompress_0x28( unsigned char *outBuf, u32 outLen, const unsigned char *inBuf, u32 inLen );
u8 *GetUnpackedTexture(u16 sheetNo);
// load a GX texture from index
GXTexObj *LoadTextureObj(u16 texture_idx);
// cmap parser
bool ParseCmap(CmapEntry *cmapEntry);
// just a duplicate check
bool CheckCmap(u16 charCode, u16 mapValue);
// get index of a character
u16 CharToIdx(u16 charCode)
{
std::map<u16, u16>::iterator itr = cmap.find(charCode);
if(itr != cmap.end())
return itr->second;
return finf->defaultChar;
}
WiiFont::Header *header;
// pointers to each sections
FinfHeader *finf;
TglpHeader *tglp;
CwdhHeader *cwdh;
GlgrHeader *glgr;
// struct to contain a decompressed texture caches
struct TextureCache
{
u8* texture_data;
bool allocated;
GXTexObj texObj;
};
std::map<u16, TextureCache> textureMap;
// character info cache map
std::map<u16, CharInfo> charInfoMap;
// holds all the character codes and their index within the font
std::map<u16, u16> cmap;
std::string name;
bool font_loaded;
};
class FontList : public std::vector<WiiFont *>
{
public:
static const u32 MAGIC = MAKE_FOURCC('f', 'n', 'l', '1');
};
#endif

51
source/banner/Window.cpp Normal file
View File

@ -0,0 +1,51 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - Dimok
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Window.h"
void Window::Load(Pane::Header *file)
{
if(!file)
return;
const u8 *section_start = (const u8 *)file;
Pane::Load(file);
header = (Window::Header *) (file+1);
// read content
QuadPane::Load((QuadPane::Header *)(section_start + header->content_offset));
// read frames
const u32 *frame_offsets = (const u32 *) (section_start + header->frame_table_offset);
for(u32 i = 0; i < header->frame_count; i++)
frames.push_back((Frame *) (section_start + frame_offsets[i]));
}
void Window::Draw(const BannerResources& resources, u8 render_alpha, const float ws_scale, Mtx &view) const
{
// TODO: handle "inflation"
// TODO: handle "frames" and "texture_flip"
QuadPane::Draw(resources, render_alpha, ws_scale, view);
}

65
source/banner/Window.h Normal file
View File

@ -0,0 +1,65 @@
/*
Copyright (c) 2010 - Wii Banner Player Project
Copyright (c) 2012 - Dimok
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef WII_BNR_WINDOW_H_
#define WII_BNR_WINDOW_H_
#include "QuadPane.h"
class Window : public QuadPane
{
public:
typedef QuadPane Base;
static const u32 MAGIC = MAKE_FOURCC('w', 'n', 'd', '1');
void Load(Pane::Header *file);
private:
void Draw(const BannerResources& resources, u8 render_alpha, const float ws_scale, Mtx &view) const;
struct inflation
{
float l, r, t, b;
};
struct Header
{
inflation infl;
u8 frame_count;
u8 pad[3];
u32 content_offset;
u32 frame_table_offset;
} __attribute__((packed));
struct Frame
{
u16 material_index;
u8 texture_flip;
} __attribute__((packed));
Header *header;
std::vector<Frame *> frames;
};
#endif

455
source/banner/ash.cpp Normal file
View File

@ -0,0 +1,455 @@
/****************************************************************************
* Copyright (C) 2012 giantpune
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "ash.h"
#include "gecko.h"
#include <stdlib.h>
#include <stdio.h>
//#include <memory.h>
#include <malloc.h>
#include <string.h>
bool IsAshCompressed( const u8 *stuff, u32 len )
{
return ( len > 0x10 &&
((*(u32*)( stuff )) & 0xFFFFFF00 ) == 0x41534800 );
}
u8* DecompressAsh( const u8 *stuff, u32 &len )
{
if( !IsAshCompressed( stuff, len ) )
{
return NULL;
}
unsigned int r[32];
unsigned int count = 0;
unsigned int t;
r[4] = (u32)stuff; //in
r[5] = 0x415348;
r[6] = 0x415348;
r[5] = s32(*(unsigned int *)(r[4]+4));
r[5] = r[5] & 0x00FFFFFF;
u32 size = r[5];
//gprintf("Decompressed size: %d\n", size);
u8* buf1 = (u8*)memalign( 32, size );
if( !buf1 )
{
gprintf( "ASH: no memory\n" );
return NULL;
}
r[3] = (u32)buf1; //out
memset( (void*)buf1, 0, size );
//printf("r[3] :%08X\n", r[3]);
//printf("\n\n");
r[24] = 0x10;
r[28] = s32(*(unsigned int *)(r[4]+8));
r[25] = 0;
r[29] = 0;
r[26] = s32(*(unsigned int *)(r[4]+0xC));
r[30] = s32(*(unsigned int *)(r[4]+r[28]));
r[28] = r[28] + 4;
//r[8] = 0x8108<<16;
//HACK, pointer to RAM
u8* workingBuffer = (u8*)memalign( 32, 0x100000 );
if( !workingBuffer )
{
gprintf( "ASH: no memory 2\n" );
free( buf1 );
return NULL;
}
r[8] = (u32)workingBuffer;
memset( (void*)workingBuffer, 0, 0x100000 );
//printf("r[8] :%08X\n", r[8]);
r[8] = r[8];
r[9] = r[8] + 0x07FE;
r[10] = r[9] + 0x07FE;
r[11] = r[10] + 0x1FFE;
r[31] = r[11] + 0x1FFE;
r[23] = 0x200;
r[22] = 0x200;
r[27] = 0;
loc_81332124:
if( r[25] != 0x1F )
goto loc_81332140;
r[0] = r[26] >> 31;
r[26]= s32(*(unsigned int *)(r[4] + r[24]));
r[25]= 0;
r[24]= r[24] + 4;
goto loc_8133214C;
loc_81332140:
r[0] = r[26] >> 31;
r[25]= r[25] + 1;
r[26]= r[26] << 1;
loc_8133214C:
if( r[0] == 0 )
goto loc_81332174;
r[0] = r[23] | 0x8000;
*(unsigned short *)(r[31]) = s16(r[0]);
r[0] = r[23] | 0x4000;
*(unsigned short *)(r[31]+2) = s16(r[0]);
r[31] = r[31] + 4;
r[27] = r[27] + 2;
r[23] = r[23] + 1;
r[22] = r[22] + 1;
goto loc_81332124;
loc_81332174:
r[12] = 9;
r[21] = r[25] + r[12];
t = r[21];
if( r[21] > 0x20 )
goto loc_813321AC;
r[21] = (~(r[12] - 0x20))+1;
r[6] = r[26] >> r[21];
if( t == 0x20 )
goto loc_8133219C;
r[26] = r[26] << r[12];
r[25] = r[25] + r[12];
goto loc_813321D0;
loc_8133219C:
r[26]= s32(*(unsigned int *)(r[4] + r[24]));
r[25]= 0;
r[24]= r[24] + 4;
goto loc_813321D0;
loc_813321AC:
r[0] = (~(r[12] - 0x20))+1;
r[6] = r[26] >> r[0];
r[26]= s32(*(unsigned int *)(r[4] + r[24]));
r[0] = (~(r[21] - 0x40))+1;
r[24]= r[24] + 4;
r[0] = r[26] >> r[0];
r[6] = r[6] | r[0];
r[25] = r[21] - 0x20;
r[26] = r[26] << r[25];
loc_813321D0:
r[12]= s16(*(unsigned short *)(r[31] - 2));
r[31] -= 2;
r[27]= r[27] - 1;
r[0] = r[12] & 0x8000;
r[12]= (r[12] & 0x1FFF) << 1;
if( r[0] == 0 )
goto loc_813321F8;
*(unsigned short *)(r[9]+r[12]) = s16(r[6]);
r[6] = (r[12] & 0x3FFF)>>1; // extrwi %r6, %r12, 14,17
if( r[27] != 0 )
goto loc_813321D0;
goto loc_81332204;
loc_813321F8:
*(unsigned short *)(r[8]+r[12]) = s16(r[6]);
r[23] = r[22];
goto loc_81332124;
loc_81332204:
r[23] = 0x800;
r[22] = 0x800;
loc_8133220C:
if( r[29] != 0x1F )
goto loc_81332228;
r[0] = r[30] >> 31;
r[30]= s32(*(unsigned int *)(r[4] + r[28]));
r[29]= 0;
r[28]= r[28] + 4;
goto loc_81332234;
loc_81332228:
r[0] = r[30] >> 31;
r[29]= r[29] + 1;
r[30]= r[30] << 1;
loc_81332234:
if( r[0] == 0 )
goto loc_8133225C;
r[0] = r[23] | 0x8000;
*(unsigned short *)(r[31]) = s16(r[0]);
r[0] = r[23] | 0x4000;
*(unsigned short *)(r[31]+2) = s16(r[0]);
r[31] = r[31] + 4;
r[27] = r[27] + 2;
r[23] = r[23] + 1;
r[22] = r[22] + 1;
goto loc_8133220C;
loc_8133225C:
r[12] = 0xB;
r[21] = r[29] + r[12];
t = r[21];
if( r[21] > 0x20 )
goto loc_81332294;
r[21] = (~(r[12] - 0x20))+1;
r[7] = r[30] >> r[21];
if( t == 0x20 )
goto loc_81332284;
r[30] = r[30] << r[12];
r[29] = r[29] + r[12];
goto loc_813322B8;
loc_81332284:
r[30]= s32(*(unsigned int *)(r[4] + r[28]));
r[29]= 0;
r[28]= r[28] + 4;
goto loc_813322B8;
loc_81332294:
r[0] = (~(r[12] - 0x20))+1;
r[7] = r[30] >> r[0];
r[30]= s32(*(unsigned int *)(r[4] + r[28]));
r[0] = (~(r[21] - 0x40))+1;
r[28]= r[28] + 4;
r[0] = r[30] >> r[0];
r[7] = r[7] | r[0];
r[29]= r[21] - 0x20;
r[30]= r[30] << r[29];
loc_813322B8:
r[12]= s16(*(unsigned short *)(r[31] - 2));
r[31] -= 2;
r[27]= r[27] - 1;
r[0] = r[12] & 0x8000;
r[12]= (r[12] & 0x1FFF) << 1;
if( r[0] == 0 )
goto loc_813322E0;
*(unsigned short *)(r[11]+r[12]) = s16(r[7]);
r[7] = (r[12] & 0x3FFF)>>1; // extrwi %r7, %r12, 14,17
if( r[27] != 0 )
goto loc_813322B8;
goto loc_813322EC;
loc_813322E0:
*(unsigned short *)(r[10]+r[12]) = s16(r[7]);
r[23] = r[22];
goto loc_8133220C;
loc_813322EC:
r[0] = r[5];
loc_813322F0:
r[12]= r[6];
loc_813322F4:
if( r[12] < 0x200 )
goto loc_8133233C;
if( r[25] != 0x1F )
goto loc_81332318;
r[31] = r[26] >> 31;
r[26] = s32(*(unsigned int *)(r[4] + r[24]));
r[24] = r[24] + 4;
r[25] = 0;
goto loc_81332324;
loc_81332318:
r[31] = r[26] >> 31;
r[25] = r[25] + 1;
r[26] = r[26] << 1;
loc_81332324:
r[27] = r[12] << 1;
if( r[31] != 0 )
goto loc_81332334;
r[12] = s16(*(unsigned short *)(r[8] + r[27]));
goto loc_813322F4;
loc_81332334:
r[12] = s16(*(unsigned short *)(r[9] + r[27]));
goto loc_813322F4;
loc_8133233C:
if( r[12] >= 0x100 )
goto loc_8133235C;
*(unsigned char *)(r[3]) = r[12];
r[3] = r[3] + 1;
r[5] = r[5] - 1;
if( r[5] != 0 )
goto loc_813322F0;
goto loc_81332434;
loc_8133235C:
r[23] = r[7];
loc_81332360:
if( r[23] < 0x800 )
goto loc_813323A8;
if( r[29] != 0x1F )
goto loc_81332384;
r[31] = r[30] >> 31;
r[30] = s32(*(unsigned int *)(r[4] + r[28]));
r[28] = r[28] + 4;
r[29] = 0;
goto loc_81332390;
loc_81332384:
r[31] = r[30] >> 31;
r[29] = r[29] + 1;
r[30] = r[30] << 1;
loc_81332390:
r[27] = r[23] << 1;
if( r[31] != 0 )
goto loc_813323A0;
r[23] = s16(*(unsigned short *)(r[10] + r[27]));
goto loc_81332360;
loc_813323A0:
r[23] = s16(*(unsigned short *)(r[11] + r[27]));
goto loc_81332360;
loc_813323A8:
r[12] = r[12] - 0xFD;
r[23] = ~r[23] + r[3] + 1;
r[5] = ~r[12] + r[5] + 1;
r[31] = r[12] >> 3;
if( r[31] == 0 )
goto loc_81332414;
count = r[31];
loc_813323C0:
r[31] = *(unsigned char *)(r[23] - 1);
*(unsigned char *)(r[3]) = r[31];
r[31] = *(unsigned char *)(r[23]);
*(unsigned char *)(r[3]+1) = r[31];
r[31] = *(unsigned char *)(r[23] + 1);
*(unsigned char *)(r[3]+2) = r[31];
r[31] = *(unsigned char *)(r[23] + 2);
*(unsigned char *)(r[3]+3) = r[31];
r[31] = *(unsigned char *)(r[23] + 3);
*(unsigned char *)(r[3]+4) = r[31];
r[31] = *(unsigned char *)(r[23] + 4);
*(unsigned char *)(r[3]+5) = r[31];
r[31] = *(unsigned char *)(r[23] + 5);
*(unsigned char *)(r[3]+6) = r[31];
r[31] = *(unsigned char *)(r[23] + 6);
*(unsigned char *)(r[3]+7) = r[31];
r[23] = r[23] + 8;
r[3] = r[3] + 8;
if( --count )
goto loc_813323C0;
r[12] = r[12] & 7;
if( r[12] == 0 )
goto loc_8133242C;
loc_81332414:
count = r[12];
loc_81332418:
r[31] = *(unsigned char *)(r[23] - 1);
r[23] = r[23] + 1;
*(unsigned char *)(r[3]) = r[31];
r[3] = r[3] + 1;
if( --count )
goto loc_81332418;
loc_8133242C:
if( r[5] != 0 )
goto loc_813322F0;
loc_81332434:
r[3] = r[0];
len = r[3];
//gprintf("Decompressed %d bytes\n", r[3]);
free( workingBuffer );
return buf1;
}

30
source/banner/ash.h Normal file
View File

@ -0,0 +1,30 @@
/****************************************************************************
* Copyright (C) 2012 giantpune
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef ASH_H
#define ASH_H
#include <gctypes.h>
// check if data is ash compressed
bool IsAshCompressed( const u8 *stuff, u32 len );
// decompress ash compressed data
//! len is the size of the compressed data, and is set to the size of the decompressed data
//! this allocates memory with memalign, free it when you are done with it
u8* DecompressAsh( const u8 *stuff, u32 &len );
#endif // ASH_H

76
source/banner/gx_addons.c Normal file
View File

@ -0,0 +1,76 @@
/****************************************************************************
* Copyright (C) 2012 Dimok
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include <gccore.h>
void GX_Project(f32 mx, f32 my, f32 mz, Mtx mv, const f32 *projection,
const f32 *viewport, f32 *sx, f32 *sy, f32 *sz)
{
float x, y, z, w;
guVector vec = (guVector) { mx, my, mz };
guVector vecRes;
guVecMultiply(mv, &vec, &vecRes);
if(projection[0] == GX_PERSPECTIVE)
{
x = (vecRes.x * projection[1]) + (vecRes.z * projection[2]);
y = (vecRes.y * projection[3]) + (vecRes.z * projection[4]);
z = (vecRes.z * projection[5]) + projection[6];
w = -1.0f / vecRes.z;
}
else
{
x = (vecRes.x * projection[1]) + projection[2];
y = (vecRes.y * projection[3]) + projection[4];
z = (vecRes.z * projection[5]) + projection[6];
w = 1.0f;
}
*sx = viewport[0] + (w * x * viewport[2] + viewport[2]) * 0.5f;
*sy = viewport[1] - (w * y * viewport[3] - viewport[3]) * 0.5f;
*sz = viewport[5] + (w * z * (viewport[5] - viewport[4]));
}
void GX_GetProjectionv( f32* ptr, Mtx44 p, u8 type)
{
ptr[0] = (f32)type;
ptr[1] = p[0][0];
ptr[3] = p[1][1];
ptr[5] = p[2][2];
ptr[6] = p[2][3];
if(type == GX_PERSPECTIVE)
{
ptr[2] = p[0][2];
ptr[4] = p[1][2];
}
else
{
ptr[2] = p[0][3];
ptr[4] = p[1][3];
}
}
void GX_GetViewportv( f32* ptr, GXRModeObj *vmode )
{
ptr[0] = 0.0f;
ptr[1] = 0.0f;
ptr[2] = vmode->fbWidth;
ptr[3] = vmode->efbHeight;
ptr[4] = 0.0f;
ptr[5] = 1.0f;
}

35
source/banner/gx_addons.h Normal file
View File

@ -0,0 +1,35 @@
/****************************************************************************
* Copyright (C) 2012 Dimok
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef GX_ADDONS_H_
#define GX_ADDONS_H_
#include <gccore.h>
#ifdef __cplusplus
extern "C" {
#endif
void GX_Project(f32 mx, f32 my, f32 mz, Mtx mv, const f32 *projection,
const f32 *viewport, f32 *sx, f32 *sy, f32 *sz);
void GX_GetProjectionv( f32* ptr, Mtx44 p, u8 type);
void GX_GetViewportv( f32* ptr, GXRModeObj *vmode );
#ifdef __cplusplus
}
#endif
#endif

View File

@ -45,7 +45,7 @@ s32 __decompressLZ77_11(u8 *in, u32 inputLen, u8 **output, u32 *outputLen)
compressedPos += 0x4;
}
printf("Decompressed size : %i\n", decompressedSize);
//printf("Decompressed size : %i\n", decompressedSize);
out = MEM2_alloc(ALIGN32(decompressedSize));
if (out == NULL)
@ -132,7 +132,7 @@ s32 __decompressLZ77_10(u8 *in, u8 **output, u32 *outputLen)
//int compressionType = (packBytes(in[0], in[1], in[2], in[3]) >> 4) & 0xF;
printf("Decompressed size : %i\n", decompressedSize);
//printf("Decompressed size : %i\n", decompressedSize);
out = MEM2_alloc(ALIGN32(decompressedSize));
if (out == NULL)
@ -200,15 +200,15 @@ int decompressLZ77content(u8 *buffer, u32 length, u8 **output, u32 *outputLen)
switch (buffer[0])
{
case LZ77_0x10_FLAG:
printf("LZ77 variant 0x10 compressed content...unpacking may take a while...\n");
//printf("LZ77 variant 0x10 compressed content...unpacking may take a while...\n");
ret = __decompressLZ77_10(buffer, output, outputLen);
break;
case LZ77_0x11_FLAG:
printf("LZ77 variant 0x11 compressed content...unpacking may take a while...\n");
//printf("LZ77 variant 0x11 compressed content...unpacking may take a while...\n");
ret = __decompressLZ77_11(buffer, length, output, outputLen);
break;
default:
printf("Not compressed ...\n");
//printf("Not compressed ...\n");
ret = -1;
break;
}

View File

@ -5,6 +5,7 @@
#define WIIFONT_NAME_KOR "Wii-kr_Round Gothic B.ttf"
const u8 WIIFONT_HASH[] = {0x32, 0xb3, 0x39, 0xcb, 0xbb, 0x50, 0x7d, 0x50, 0x27, 0x79, 0x25, 0x9a, 0x78, 0x66, 0x99, 0x5d, 0x03, 0x0b, 0x1d, 0x88};
const u8 WIIFONT_HASH_KOR[] = {0xb7, 0x15, 0x6d, 0xf0, 0xf4, 0xae, 0x07, 0x8f, 0xd1, 0x53, 0x58, 0x3e, 0x93, 0x6e, 0x07, 0xc0, 0x98, 0x77, 0x49, 0x0e};
const u8 WFB_HASH[] = { 0x4f, 0xad, 0x97, 0xfd, 0x4a, 0x28, 0x8c, 0x47, 0xe0, 0x58, 0x7f, 0x3b, 0xbd, 0x29, 0x23, 0x79, 0xf8, 0x70, 0x9e, 0xb9 };
#define FONT_BOLD 36u
#define FONT_NOBOLD 8u

View File

@ -169,6 +169,10 @@ void CVideo::init(void)
GX_SetNumChans(0);
GX_SetZCompLoc(GX_ENABLE);
setup2DProjection();
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
for(u32 i = 0; i < 8; i++)
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0+i, GX_TEX_ST, GX_F32, 0);
_clearScreen();
VIDEO_SetBlack(FALSE);
VIDEO_Flush();

View File

@ -58,6 +58,7 @@ public:
void setup2DProjection(bool setViewPort = true, bool noScale = false);
u32 width(void) const { return m_rmode->fbWidth; }
u32 height(void) const { return m_rmode->efbHeight; }
GXRModeObj *vid_mode(void) const { return m_rmode; }
u32 width2D(void) { return m_width2D; }
u32 height2D(void) { return m_height2D; }
bool wide(void) const { return m_wide; }

View File

@ -25,6 +25,7 @@
#include "gc/fileOps.h"
#include "Gekko.h"
#include "GameTDB.hpp"
#include "BannerWindow.hpp"
// Sounds
extern const u8 click_wav[];
@ -109,6 +110,10 @@ extern const u8 butzhcnoffs_png[];
extern const u8 checkbox_png[];
extern const u8 checkboxs_png[];
SmartBuf m_wbf1_font;
SmartBuf m_wbf2_font;
BannerWindow m_banner;
CMenu::CMenu(CVideo &vid) :
m_vid(vid)
{
@ -472,7 +477,7 @@ void CMenu::cleanup(bool ios_reload)
m_cf.stopCoverLoader();
m_cf.clear();
ClearGameSoundThreadStack();
m_banner.DeleteBanner();
m_plugin.Cleanup();
_stopSounds();
@ -1758,11 +1763,12 @@ void CMenu::_mainLoopCommon(bool withCF, bool blockReboot, bool adjusting)
}
m_fa.draw();
if(m_banner.GetSelectedGame())
m_banner.Draw();
m_btnMgr.draw();
ScanInput();
m_vid.setup2DProjection();
m_vid.render();
if(!blockReboot)
{
@ -2327,9 +2333,7 @@ retry:
if(u8_font_archive != NULL)
{
const u8 *font_file = u8_get_file_by_index(u8_font_archive, 1, &size); // There is only one file in that app
//gprintf("Extracted font: %d\n", size);
m_base_font = smartMem2Alloc(size);
memcpy(m_base_font.get(), font_file, size);
if(!!m_base_font)
@ -2338,6 +2342,26 @@ retry:
}
break;
}
else if(memcmp(cm[i].sha1, WFB_HASH, 20) == 0)
{
// Name found, load it and unpack it
char font_filename[32] ATTRIBUTE_ALIGN(32);
strcpy(font_filename, "/shared1/XXXXXXXX.app"); // Faster than sprintf
memcpy(font_filename+9, cm[i].filename, 8);
u8 *u8_font_archive = ISFS_GetFile((u8 *)font_filename, &size, 0);
if(u8_font_archive != NULL)
{
const u8 *font_file1 = u8_get_file(u8_font_archive, "wbf1.brfna", &size);
m_wbf1_font = smartMem2Alloc(size);
memcpy(m_wbf1_font.get(), font_file1, size);
const u8 *font_file2 = u8_get_file(u8_font_archive, "wbf2.brfna", &size);
m_wbf2_font = smartMem2Alloc(size);
memcpy(m_wbf2_font.get(), font_file2, size);
MEM2_free(u8_font_archive);
}
}
}
if (!retry)
@ -2353,6 +2377,9 @@ void CMenu::_cleanupDefaultFont()
{
m_base_font.release();
m_base_font_size = 0;
m_wbf1_font.release();
m_wbf2_font.release();
}
const char *CMenu::_domainFromView()

View File

@ -73,7 +73,6 @@ private:
Config m_titles;
Config m_version;
Plugin m_plugin;
Channels m_channels;
vector<string> m_homebrewArgs;
SmartBuf m_base_font;
u32 m_base_font_size;
@ -147,10 +146,6 @@ private:
STexture m_gameBgLQ;
STexture m_mainBgLQ;
STexture m_categoryBg;
//
u32 m_errorLblMessage;
u32 m_errorLblIcon;
u32 m_errorLblUser[4];
//Main Coverflow
u32 m_mainBtnConfig;
u32 m_mainBtnInfo;

View File

@ -16,6 +16,8 @@ static inline int loopNum(int i, int s)
int currentChannelIndex = -1;
int amountOfChannels = -1;
Channels m_channels;
const CMenu::SOption CMenu::_exitTo[6] = {
{ "def", L"Default" },
{ "menu", L"System Menu" },

View File

@ -3,6 +3,9 @@
#include "gecko.h"
extern const u8 error_png[];
u32 m_errorLblMessage;
u32 m_errorLblIcon;
u32 m_errorLblUser[4];
void CMenu::error(const wstringEx &msg)
{

View File

@ -17,6 +17,7 @@
#include "wip.h"
#include "channel_launcher.h"
#include "devicemounter/sdhc.h"
#include "BannerWindow.hpp"
#include <network.h>
#include <errno.h>
@ -57,6 +58,8 @@ extern u32 sector_size;
extern int mainIOS;
static u64 sm_title_id[8] ATTRIBUTE_ALIGN(32);
bool m_zoom_banner;
const string CMenu::_translations[23] = {
"Default",
"Arab",
@ -359,17 +362,19 @@ void CMenu::_game(bool launch)
m_gameSelected = true;
}
extern BannerWindow m_banner;
string id(m_cf.getId());
s8 startGameSound = 1;
while(true)
{
if(startGameSound < 1)
startGameSound++;
string id(m_cf.getId());
u64 chantitle = m_cf.getChanTitle();
if(startGameSound == -5)
{
id = m_cf.getId();
_playGameSound();
_showGame();
}
@ -392,6 +397,7 @@ void CMenu::_game(bool launch)
m_gameSound.FreeMemory();
CheckGameSoundThread();
ClearGameSoundThreadStack();
m_banner.DeleteBanner();
break;
}
else if(BTN_PLUS_PRESSED && m_GameTDBLoaded && (m_cf.getHdr()->type == TYPE_WII_GAME || m_cf.getHdr()->type == TYPE_GC_GAME || m_cf.getHdr()->type == TYPE_CHANNEL))
@ -466,9 +472,19 @@ void CMenu::_game(bool launch)
m_gcfg1.setBool("ADULTONLY", id, !m_gcfg1.getBool("ADULTONLY", id, false));
else if(m_btnMgr.selected(m_gameBtnBack))
{
m_gameSound.Stop();
CheckGameSoundThread();
break;
//m_gameSound.Stop();
//CheckGameSoundThread();
//break;
if(m_zoom_banner)
{
m_banner.ZoomOut();
m_zoom_banner = false;
}
else
{
m_banner.ZoomIn();
m_zoom_banner = true;
}
}
else if(m_btnMgr.selected(m_gameBtnSettings))
{
@ -1425,6 +1441,8 @@ void CMenu::_initGameMenu(CMenu::SThemeData &theme)
_setHideAnim(m_gameBtnDelete, "GAME/DELETE_BTN", 0, 0, -1.5f, -1.5f);
_hideGame(true);
_textGame();
m_zoom_banner = false;
}
void CMenu::_textGame(void)
@ -1476,7 +1494,12 @@ void CMenu::_gameSoundThread(CMenu *m)
}
_extractBannerTitle(banner, GetLanguage(m->m_loc.getString(m->m_curLanguage, "gametdb_code", "EN").c_str()));
extern SmartBuf m_wbf1_font;
extern SmartBuf m_wbf2_font;
extern BannerWindow m_banner;
const u8 *soundBin = banner->GetFile((char *) "sound.bin", &sndSize);
m_banner.LoadBanner(banner, &m->m_vid, m_wbf1_font.get(), m_wbf2_font.get());
delete banner;
if (soundBin == NULL || (((IMD5Header *)soundBin)->fcc != 'IMD5' && ((IMD5Header *)soundBin)->fcc != 'RIFF'))

View File

@ -480,7 +480,7 @@ void GuiSound::UncompressSoundbin(const u8 * snd, u32 len, bool isallocated)
if(isallocated)
{
void *p = (void *)snd;
MEM1_free(p);
free(p);
}
allocated = true;