new font, rewritten PNGU, menu tweaks, optimized text code

This commit is contained in:
dborth 2010-03-21 19:52:22 +00:00
parent a126568d04
commit 3b8b7b74d1
8 changed files with 946 additions and 638 deletions

Binary file not shown.

View File

@ -109,7 +109,7 @@ GuiFileBrowser::GuiFileBrowser(int w, int h)
fileListText[i] = new GuiText(NULL, 20, (GXColor){0, 0, 0, 0xff});
fileListText[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
fileListText[i]->SetPosition(5,0);
fileListText[i]->SetMaxWidth(380);
fileListText[i]->SetMaxWidth(450);
fileListBg[i] = new GuiImage(bgFileSelectionEntry);
fileListIcon[i] = NULL;

View File

@ -20,40 +20,7 @@ GuiImageData::GuiImageData(const u8 * i)
height = 0;
if(i)
{
PNGUPROP imgProp;
IMGCTX ctx = PNGU_SelectImageFromBuffer(i);
if(!ctx)
return;
int res = PNGU_GetImageProperties(ctx, &imgProp);
if(res == PNGU_OK)
{
int len = (imgProp.imgWidth * imgProp.imgHeight) <<2;
if(len%32) len += (32-len%32);
data = (u8 *)memalign (32, len);
if(data)
{
res = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, data, 255);
if(res == PNGU_OK)
{
width = imgProp.imgWidth;
height = imgProp.imgHeight;
DCFlushRange(data, len);
}
else
{
free(data);
data = NULL;
}
}
}
PNGU_ReleaseImageContext (ctx);
}
data = DecodePNG(i, &width, &height);
}
/**

View File

@ -237,126 +237,130 @@ void GuiText::Draw()
fontSystem[newSize] = new FreeTypeGX(newSize);
currentSize = newSize;
}
u8 maxChar;
if(maxWidth > 0)
{
char * tmpText = strdup(origText);
u8 maxChar = int((float((maxWidth<<1))) / (float(newSize)));
if(!textDyn)
{
if(strlen(tmpText) > maxChar)
tmpText[maxChar] = 0;
textDyn = charToWideChar(tmpText);
}
if(textScroll == SCROLL_HORIZONTAL)
{
int textlen = strlen(origText);
if(textlen > maxChar && (FrameTimer % textScrollDelay == 0))
{
if(textScrollInitialDelay)
{
--textScrollInitialDelay;
}
else
{
++textScrollPos;
if(textScrollPos > textlen-1)
{
textScrollPos = 0;
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
}
strncpy(tmpText, &origText[textScrollPos], maxChar-1);
tmpText[maxChar-1] = 0;
int dynlen = strlen(tmpText);
if(dynlen+2 < maxChar)
{
tmpText[dynlen] = ' ';
tmpText[dynlen+1] = ' ';
strncat(&tmpText[dynlen+2], origText, maxChar - dynlen - 2);
}
if(textDyn) delete[] textDyn;
textDyn = charToWideChar(tmpText);
}
}
if(textDyn)
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), textDyn, c, style);
}
else if(wrap)
{
int lineheight = newSize + 6;
int txtlen = wcslen(text);
int i = 0;
int ch = 0;
int linenum = 0;
int lastSpace = -1;
int lastSpaceIndex = -1;
wchar_t * textrow[20];
while(ch < txtlen)
{
if(i == 0)
textrow[linenum] = new wchar_t[txtlen + 1];
textrow[linenum][i] = text[ch];
textrow[linenum][i+1] = 0;
if(text[ch] == ' ' || ch == txtlen-1)
{
if(wcslen(textrow[linenum]) >= maxChar)
{
if(lastSpace >= 0)
{
textrow[linenum][lastSpaceIndex] = 0; // discard space, and everything after
ch = lastSpace; // go backwards to the last space
lastSpace = -1; // we have used this space
lastSpaceIndex = -1;
}
++linenum;
i = -1;
}
else if(ch == txtlen-1)
{
++linenum;
}
}
if(text[ch] == ' ' && i >= 0)
{
lastSpace = ch;
lastSpaceIndex = i;
}
++ch;
++i;
}
int voffset = 0;
if(alignmentVert == ALIGN_MIDDLE)
voffset = (lineheight >> 1) * (1-linenum);
int left = this->GetLeft();
int top = this->GetTop() + voffset;
for(i=0; i < linenum; ++i)
{
fontSystem[currentSize]->drawText(left, top+i*lineheight, textrow[i], c, style);
delete[] textrow[i];
}
}
else
{
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), textDyn, c, style);
}
free(tmpText);
}
else
if(maxWidth == 0)
{
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), text, c, style);
goto done;
}
maxChar = int((float((maxWidth<<1))) / (float(newSize))); // approximate
if(wrap)
{
int lineheight = newSize + 6;
int txtlen = wcslen(text);
int i = 0;
int ch = 0;
int linenum = 0;
int lastSpace = -1;
int lastSpaceIndex = -1;
wchar_t * textrow[20];
while(ch < txtlen)
{
if(i == 0)
textrow[linenum] = new wchar_t[txtlen + 1];
textrow[linenum][i] = text[ch];
textrow[linenum][i+1] = 0;
if(text[ch] == ' ' || ch == txtlen-1)
{
if(wcslen(textrow[linenum]) >= maxChar)
{
if(lastSpace >= 0)
{
textrow[linenum][lastSpaceIndex] = 0; // discard space, and everything after
ch = lastSpace; // go backwards to the last space
lastSpace = -1; // we have used this space
lastSpaceIndex = -1;
}
++linenum;
i = -1;
}
else if(ch == txtlen-1)
{
++linenum;
}
}
if(text[ch] == ' ' && i >= 0)
{
lastSpace = ch;
lastSpaceIndex = i;
}
++ch;
++i;
}
int voffset = 0;
if(alignmentVert == ALIGN_MIDDLE)
voffset = (lineheight >> 1) * (1-linenum);
int left = this->GetLeft();
int top = this->GetTop() + voffset;
for(i=0; i < linenum; ++i)
{
fontSystem[currentSize]->drawText(left, top+i*lineheight, textrow[i], c, style);
delete[] textrow[i];
}
goto done;
}
if(textScroll == SCROLL_HORIZONTAL)
{
char *tmpText = strdup(gettext(origText));
char *tmpText2 = strdup(tmpText);
int textlen = strlen(tmpText);
if(textlen > maxChar && (FrameTimer % textScrollDelay == 0))
{
if(textScrollInitialDelay)
{
--textScrollInitialDelay;
}
else
{
++textScrollPos;
if(textScrollPos > textlen-1)
{
textScrollPos = 0;
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
}
strncpy(tmpText, &tmpText2[textScrollPos], maxChar-1);
tmpText[maxChar-1] = 0;
int dynlen = strlen(tmpText);
if(dynlen+2 < maxChar)
{
tmpText[dynlen] = ' ';
tmpText[dynlen+1] = ' ';
strncat(&tmpText[dynlen+2], tmpText2, maxChar - dynlen - 2);
}
if(textDyn) delete[] textDyn;
textDyn = charToWideChar(tmpText);
}
}
free(tmpText);
free(tmpText2);
}
if(!textDyn)
{
char *tmpText = strdup(gettext(origText));
if(strlen(tmpText) > maxChar)
tmpText[maxChar] = 0;
textDyn = charToWideChar(tmpText);
free(tmpText);
}
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), textDyn, c, style);
done:
this->UpdateEffects();
}

View File

@ -1,23 +1,53 @@
msgid " "
msgstr " "
msgid "&"
msgstr "&"
msgid "16:9 Correction"
msgstr "Correction 16:9"
msgid "7z decompression failed: Archive contains too many files"
msgstr "La décompression 7z a échoué : l'archive contient trop de fichiers"
msgid "7z decompression failed: Failed to read file data"
msgstr "La décompression 7z a échoué : la lecture des données du fichier a échoué"
msgid "7z decompression failed: File is corrupt"
msgstr "La décompression 7z a échoué : le fichier est corrompu"
msgid "7z decompression failed: File is corrupt (CRC mismatch)"
msgstr "La décompression 7z a échoué : le fichier est corrompu (erreur de contrôle de redondance cyclique - CRC)"
msgid "7z decompression failed: File uses too high of compression settings (dictionary size is too large)"
msgstr "La décompression 7z a échoué : le fichier utilise un paramètre de compression trop élevé (taille du dictionnaire trop haute)"
msgid "7z decompression failed: File uses unsupported compression settings"
msgstr "La décompression 7z a échoué : le fichier utilise des paramètres de compression non supportés"
msgid "A (Rapid)"
msgstr "A (Rapide)"
msgid "Aim Offscreen"
msgstr "Visée hors champ"
msgid "An update is available!"
msgstr "Une mise à jour est disponible!"
msgstr "Une mise à jour est disponible !"
msgid "Are you sure that you want to reset this game? Any unsaved progress will be lost."
msgstr "Êtes-vous sûr de vouloir redémarrer ce jeu ? Toute progression non sauvegardée sera perdue."
msgid "Are you sure that you want to reset your mappings?"
msgstr "Êtes-vous sûr de vouloir réinitialiser les touches?"
msgstr "Êtes-vous sûr de vouloir réinitialiser les touches ?"
msgid "Are you sure that you want to reset your settings?"
msgstr "Êtes-vous sûr de vouloir réinitialiser les paramètres?"
msgstr "Êtes-vous sûr de vouloir réinitialiser tout les paramètres ?"
msgid "Maintain Aspect Ratio"
msgstr "Conserver les proportions"
msgid "Attempting to determine load device..."
msgstr "Tentative de détection du périphérique d'entrée..."
msgid "Attempting to determine save device..."
msgstr "Tentative de détection du périphérique de sauvegarde..."
msgid "Auto"
msgstr "Auto"
@ -34,6 +64,9 @@ msgstr "Sauvegarde Auto"
msgid "Automatic (Recommended)"
msgstr "Automatique (Recommandé)"
msgid "B (Rapid)"
msgstr "B (Rapide)"
msgid "Back"
msgstr "Retour"
@ -56,7 +89,7 @@ msgid "Cheats"
msgstr "Cheats"
msgid "Cheats file not found!"
msgstr "Fichier Cheats non trouvé!"
msgstr "Fichier Cheats non trouvé !"
msgid "Cheats Folder"
msgstr "Dossier Cheats"
@ -74,7 +107,13 @@ msgid "Coding"
msgstr "Programmation"
msgid "Coding & menu design"
msgstr "Program. & design du menu"
msgstr "Prog. & design du menu"
msgid "Compressed GBA files are not supported!"
msgstr "Les fichiers GBA compressés ne sont pas supportés !"
msgid "Connecting to network share..."
msgstr "Connection au partage réseau en cours..."
msgid "Controller"
msgstr "Contrôleur"
@ -88,12 +127,30 @@ msgstr "Dossier des jaquettes"
msgid "Credits"
msgstr "Crédits"
msgid "Cropping"
msgstr "Recadrage"
msgid "Crosshair"
msgstr "Réticule de visée"
msgid "Cursor"
msgstr "Curseur"
msgid "Data DVD"
msgstr "Données DVD"
msgid "Default"
msgstr "Par défaut"
msgid "Directory name is too long!"
msgstr "Le nom du répertoire est trop long !"
msgid "Disabled"
msgstr "Désactivé"
msgid "DISABLED"
msgstr "DÉSACTIVÉ"
msgid "distributed, or modified under the terms of the"
msgstr "distribuée, ou modifiée selon les termes de"
@ -106,17 +163,65 @@ msgstr "Bas"
msgid "DOWN"
msgstr "BAS"
msgid "Downloading..."
msgstr "Téléchargement en cours..."
msgid "Dutch"
msgstr "Néerlandais"
msgid "Empty or invalid ZIP file!"
msgstr "Fichier ZIP vide ou invalide !"
msgid "Enabled"
msgstr "Activé"
msgid "ENABLED"
msgstr "ACTIVÉ"
msgid "English"
msgstr "Anglais"
msgid "Error"
msgstr "Erreur"
msgid "Error - Invalid ZIP file!"
msgstr "Erreur - Fichier ZIP invalide !"
msgid "Error creating file!"
msgstr "Une erreur est survenue à la création du fichier !"
msgid "Error loading game!"
msgstr "Erreur de chargement du jeu !"
msgid "Error opening archive!"
msgstr "Erreur lors de l'ouverture de l'archive !"
msgid "Error opening directory!"
msgstr "Erreur lors de l'ouverture du répertoire !"
msgid "Error opening file!"
msgstr "Erreur lors de l'ouverture du fichier !"
msgid "Error reading file!"
msgstr "Une erreur est survenue à la lecture du fichier !"
msgid "Error saving file!"
msgstr "Erreur lors de la sauvegarde du fichier !"
msgid "Exit"
msgstr "Sortir"
msgid "Exit Action"
msgstr "Sortie de SNES9xGx"
msgstr "Sortie de l'émulateur"
msgid "Failed to connect to network share."
msgstr "La connection au partage réseau a échoué."
msgid "FDS BIOS file is invalid!"
msgstr "Le fichier du BIOS du FDS (Famicom Disk System) est invalide !"
msgid "FDS BIOS file not found!"
msgstr "Le fichier du BIOS du FDS (Famicom Disk System) est introuvable !"
msgid "Filtered"
msgstr "Filtré"
@ -124,6 +229,18 @@ msgstr "Filtré"
msgid "Filtering"
msgstr "Filtrage"
msgid "Fire"
msgstr "Tirer"
msgid "French"
msgstr "Français"
msgid "GBA Screen Zoom"
msgstr "Zoom écran GBA"
msgid "Game Genie ROM not found!"
msgstr "La ROM Game Genie est introuvable !"
msgid "Game Settings"
msgstr "Configuration"
@ -136,9 +253,21 @@ msgstr "Configuration - Cheats"
msgid "Game Settings - Video"
msgstr "Configuration - Vidéo"
msgid "Game Timing"
msgstr "Timing du jeu"
msgid "Game Genie DISABLED"
msgstr "Game Genie Désactivé"
msgid "Game Genie ENABLED"
msgstr "Game Genie Activé"
msgid "GameCube Controller"
msgstr "Manette Gamecube"
msgid "German"
msgstr "Allemand"
msgid "GNU General Public License (GPL) Version 2."
msgstr "la Licence Publique Générale (GPL) GNU Version 2."
@ -151,8 +280,56 @@ msgstr "Horizontal"
msgid "Information"
msgstr "Information"
msgid "Initializing network..."
msgstr "Initialisation du réseau en cours..."
msgid "Insert Coin"
msgstr "Insérer une pièce"
msgid "Insert Coin / Switch Disk"
msgstr "Insér. une pièce/Chang. disq."
msgid "Invalid file size!"
msgstr "Taille du fichier invalide"
msgid "Invalid game file!"
msgstr "Taille du fichier du jeu invalide"
msgid "Invalid network settings - Check settings.xml."
msgstr "Paramètres réseau invalides - Veuillez vérifier le fichier settings.xml."
msgid "Invalid network settings - Share IP is blank."
msgstr "Paramètres réseau invalides - L'IP partagée n'est pas renseignée."
msgid "Invalid network settings - Share name is blank."
msgstr "Paramètres réseau invalides - Le nom du partage n'est pas renseigné."
msgid "Invalid save file"
msgstr "Fichier de sauvegarde invalide"
msgid "Invalid state file"
msgstr "Fichier de sauvegarde d'état invalide"
msgid "Italian"
msgstr "Italien"
msgid "Japanese"
msgstr "Japonais"
msgid "Justifier"
msgstr "Justifier"
msgstr "Konami Justifier"
msgid "Justifier - GameCube Controller"
msgstr "Konami Justifier - Manette GameCube"
msgid "Justifier - Wiimote"
msgstr "Konami Justifier - Wiimote"
msgid "Korean"
msgstr "Coréen"
msgid "L TRIG"
msgstr "L"
msgid "Language"
msgstr "Langage"
@ -166,6 +343,9 @@ msgstr "Gauche"
msgid "LEFT"
msgstr "GAUCHE"
msgid "Left Button"
msgstr "Clic gauche"
msgid "Load"
msgstr "Charger"
@ -181,9 +361,24 @@ msgstr "Charger une partie"
msgid "Loading"
msgstr "Chargement"
msgid "Loading DVD..."
msgstr "Chargement du DVD en cours..."
msgid "Loading patch..."
msgstr "Chargement du patch en cours..."
msgid "Loading..."
msgstr "Chargement en cours..."
msgid "Main Menu"
msgstr "Menu Principal"
msgid "Match Wii Controls"
msgstr "Jouabilité Wii identique"
msgid "Maximum filepath length reached!"
msgid "La longueur maximale du chemin d'accés est atteinte !"
msgid "Menu"
msgstr "Menu"
@ -202,21 +397,54 @@ msgstr "Volume de la Musique"
msgid "Mute"
msgstr "Muet"
msgid "NES Controller"
msgstr "Manette NES"
msgid "NES Controllers (2)"
msgstr "Manettes NES (2)"
msgid "NES Controllers (4)"
msgstr "Manettes NES (4)"
msgid "NES Zapper"
msgstr "Nintendo Zapper"
msgid "Network"
msgstr "Réseau"
msgid "Network Share"
msgstr "Partage réseau"
msgid "New"
msgstr "Nouv."
msgstr "Nouvelle"
msgid "New Snapshot"
msgstr "Nouvelle sauvegarde d'état"
msgid "New SRAM"
msgstr "Nouvelle sauvegarde SRAM"
msgid "No"
msgstr "Non"
msgstr "Non"
msgid "None"
msgstr "Aucun"
msgid "No data to save!"
msgstr "Pas de données (RAM) à sauvegarder !"
msgid "No disc inserted!"
msgstr "Aucun disque inséré !"
msgid "No SRAM data to save!"
msgstr "Pas de données SRAM à sauvegarder !"
msgid "No game saves found."
msgstr "Aucune sauvegarde trouvée."
msgid "None"
msgstr "Aucun"
msgid "NTSC (480i)"
msgstr "NTSC (480i)"
@ -226,9 +454,15 @@ msgstr "Nunchuk"
msgid "Off"
msgstr "Off"
msgid "Official Site: http://code.google.com/p/fceugc/"
msgstr "Site Officiel: http://code.google.com/p/fceugc/"
msgid "Official Site: http://code.google.com/p/snes9x-gx/"
msgstr "Site Officiel: http://code.google.com/p/snes9x-gx/"
msgid "Official Site: http://code.google.com/p/vba-wii/"
msgstr "Site Officiel: http://code.google.com/p/vba-wii/"
msgid "OK"
msgstr "OK"
@ -238,20 +472,56 @@ msgstr "On"
msgid "Original"
msgstr "Original"
msgid "Out of memory!"
msgstr "Mémoire insuffisante !"
msgid "Out of memory: too many files!"
msgstr "Mémoire insuffisante : trop de fichiers !"
msgid "P 1"
msgstr "J1"
msgid "P2"
msgstr "J2"
msgid "P3"
msgstr "J3"
msgid "P4"
msgstr "J4"
msgid "PAL (50Hz)"
msgstr "PAL (50Hz)"
msgid "PAL (60Hz)"
msgstr "PAL (60Hz)"
msgid "Palette saved"
msgstr "La palette est sauvegardée"
msgid "Partial Stretch"
msgstr "Étirer partiellement"
msgid "Pause"
msgstr "Pause"
msgid "Please install IOS 202 for DVD support."
msgstr "Veuillez installer l'IOS 202 pour le support du DVD"
msgid "Please Wait"
msgstr "Veuillez patienter"
msgid "PLUS"
msgstr "PLUS"
msgid "Portuguese"
msgstr "Portugais"
msgid "Power off Wii"
msgstr "Eteindre la Wii"
msgstr "Éteindre la Wii"
msgid "Preferences saved"
msgstr "Les préférences ont été sauvegardés"
msgid "Press any button on the Classic Controller now. Press Home to clear the existing mapping."
msgstr "Appuyer sur un bouton de la manette Classique. Appuyer sur HOME pour effacer le paramètre actuel."
@ -277,6 +547,12 @@ msgstr "Quitter le Jeu"
msgid "Quit this game? Any unsaved progress will be lost."
msgstr "Quitter ce jeu ? Toute progression non sauvegardée sera perdue."
msgid "R TRIG"
msgstr "R"
msgid "RAM saving is not available for FDS games!"
msgstr "La sauvegarde RAM n'est pas disponible pour les jeux sur disquette (Famicom Disk System) !"
msgid "Reboot"
msgstr "Redémarrer"
@ -289,6 +565,9 @@ msgstr "Réinitialiser"
msgid "Reset Game"
msgstr "Réinitialiser le Jeu"
msgid "Reset this game? Any unsaved progress will be lost."
msgstr "Redémarrer ce jeu ? Toute progression non sauvegardée sera perdue."
msgid "Reset Mappings"
msgstr "Réinit. les touches"
@ -310,6 +589,9 @@ msgstr "Droite"
msgid "RIGHT"
msgstr "DROITE"
msgid "Right Button"
msgstr "Clic droit"
msgid "Rumble"
msgstr "Vibration"
@ -319,17 +601,29 @@ msgstr "Sauver"
msgid "Save Device"
msgstr "Périph. de sauvegarde"
msgid "Save failed!"
msgstr "La sauvegarde a échoué !"
msgid "Save file not found"
msgstr "Pas de fichier de sauvegarde trouvé"
msgid "Save Folder"
msgstr "Dossier des sauv."
msgid "Save Game"
msgstr "Sauvegarder la partie"
msgid "Save RAM and State?"
msgstr "Sauver la RAM et la position du jeu (sauvegarde d'état) ?"
msgid "Save Snapshot?"
msgstr "Sauver la position du jeu ?"
msgstr "Sauver la position du jeu (sauvegarde d'état) ?"
msgid "Save SRAM and Snapshot?"
msgstr "Sauver la SRAM et la position du jeu ?"
msgstr "Sauver la SRAM et la position du jeu (sauvegarde d'état) ?"
msgid "Save State?"
msgstr "Sauver la position du jeu (sauvegarde d'état) ?"
msgid "Save successful"
msgstr "Sauvegarde réussie"
@ -337,6 +631,12 @@ msgstr "Sauvegarde réussie"
msgid "Saving"
msgstr "Sauvegarde"
msgid "Saving preferences..."
msgstr "Sauvegarde des préférences en cours..."
msgid "Saving..."
msgstr "Sauvegarde en cours..."
msgid "Scaling"
msgstr "Format"
@ -346,6 +646,12 @@ msgstr "Position de l'écran"
msgid "Screen Zoom"
msgstr "Zoom écran"
msgid "Select"
msgstr "Select"
msgid "Seek error!"
msgstr "Erreur de positionnement ! (seek error)"
msgid "Settings"
msgstr "Paramètres"
@ -356,25 +662,37 @@ msgid "Settings - Network"
msgstr "Paramètres - Réseau"
msgid "Settings - Saving & Loading"
msgstr "Paramètres - Sauv. & Chargement"
msgstr "Paramètres - Sauvegarde & Chargement"
msgid "SD Card"
msgstr "Carte SD"
msgid "SD card not found!"
msgstr "Carte SD introuvable !"
msgid "Shift"
msgstr "Maj"
msgid "Simp_chinese"
msgstr "Chinois simplifié"
msgid "SMB Share IP"
msgstr "IP Partage SMB"
msgstr "IP partagée SMB"
msgid "SMB Share Name"
msgstr "Nom Partage SMB"
msgstr "Nom du Partage SMB"
msgid "SMB Share Password"
msgstr "Mot de passe partage SMB"
msgstr "Mot de passe de partage SMB"
msgid "SMB Share Username"
msgstr "Utilisateur Partage SMB"
msgstr "Nom d'utilisateur de partage SMB"
msgid "Snapshot"
msgstr "Sauv. d'état"
msgstr "Sauvegarde d'état"
msgid "Snapshot (Auto)"
msgstr "Sauv. d'état (Auto)"
msgid "SNES Controller"
msgstr "Manette SNES"
@ -385,27 +703,93 @@ msgstr "Manettes SNES (2)"
msgid "SNES Controllers (4)"
msgstr "Manettes SNES (4)"
msgid "SNES Mouse"
msgstr "Souris SNES"
msgid "SNES Controller - Classic Controller"
msgstr "Manette SNES - Manette Classique"
msgid "SNES Controller - GameCube Controller"
msgstr "Manette SNES - Manette GameCube"
msgid "SNES Controller - Nunchuk + Wiimote"
msgstr "Manette SNES - Nunchuk + Wiimote"
msgid "SNES Controller - Wiimote"
msgstr "Manette SNES - Wiimote"
msgid "SNES Mouse"
msgstr "Souris SNES"
msgid "SNES Mouse - GameCube Controller"
msgstr "Souris SNES - Manette GameCube"
msgid "SNES Mouse - Wiimote"
msgstr "Souris SNES - Wiimote"
msgid "Snes9x - Copyright (c) Snes9x Team 1996 - 2006"
msgstr "Snes9x - Copyright (c) Snes9x Team 1996 - 2006"
msgid "Sound Effects Volume"
msgstr "Volume des effets sonores"
msgid "Super Scope"
msgid "Spanish"
msgstr "Espagnol"
msgid "Sprite Limit"
msgstr "Limite de Sprites"
msgid "SRAM file not found"
msgstr "Pas de sauvegarde SRAM trouvée"
msgid "State"
msgstr "Sauvegarde d'état"
msgid "State (Auto)"
msgstr "Sauv. d'état (Auto)"
msgid "State file not found"
msgstr "Pas de sauvegarde d'état trouvée"
msgid "Stretch to Fit"
msgstr "Plein écran"
msgid "Superscope"
msgstr "Super Scope"
msgid "Superscope - GameCube Controller"
msgstr "Super Scope - Manette GameCube"
msgid "Superscope - Wiimote"
msgstr "Super Scope - Wiimote"
msgid "This software is open source and may be copied,"
msgstr "Cette application est libre et peut être copiée,"
msgid "Trad_chinese"
msgstr "Chinois traditionnel"
msgid "Unable to initialize network!"
msgstr "Impossible d'initialiser le réseau !"
msgid "Unable to locate a load device!"
msgstr "Périphérique d'entrée introuvable !"
msgid "Unable to locate a save device!"
msgstr "Périphérique de sauvegarde introuvable !"
msgid "Unable to open snapshot!"
msgstr "Impossible d'ouvrir la sauvegarde d'état"
msgid "Unfiltered"
msgstr "Non-filtré"
msgid "Unknown file type!"
msgstr "Type de fichier inconnu !"
msgid "Unrecognized DVD format."
msgstr "Format du DVD inconnu."
msgid "Unrecognized file extension!"
msgstr "L'extension du fichier est inconnu !"
msgid "Up"
msgstr "Haut"
@ -418,11 +802,23 @@ msgstr "Dossier Parent"
msgid "Update Available"
msgstr "Mise à jour disponible"
msgid "Update failed!"
msgstr "La mise à jour a échouée !"
msgid "Update later"
msgstr "Mise à jour Plus tard"
msgstr "Mise à jour plus tard"
msgid "Update now"
msgstr "Mise à jour Maintenant"
msgstr "Mise à jour maintenant"
msgid "Update successful!"
msgstr "La mise à jour a réussie !"
msgid "USB drive not found!"
msgstr "Aucun disque USB n'a été trouvé !"
msgid "USB Mass Storage"
msgstr "Périphérique de stockage USB"
msgid "Vertical"
msgstr "Vertical"
@ -433,6 +829,15 @@ msgstr "Vidéo"
msgid "Video Mode"
msgstr "Mode Vidéo"
msgid "VM8: Unknown page type!"
msgstr "VM8 : Type de page inconnu !"
msgid "VM16: Unknown page type!"
msgstr "VM16 : Type de page inconnu !"
msgid "VM32: Unknown page type!"
msgstr "VM32 : Type de page inconnu !"
msgid "Wiimote"
msgstr "Wiimote"
@ -441,4 +846,9 @@ msgstr "Orientation de la Wiimote"
msgid "Yes"
msgstr "Oui"
msgid "Zapper"
msgstr "Nintendo Zapper"
msgid "Zapper Crosshair"
msgstr "Réticule du Zapper"

View File

@ -795,41 +795,41 @@ static void WindowCredits(void * ptr)
FTGX_JUSTIFY_LEFT | FTGX_ALIGN_TOP, ALIGN_LEFT, ALIGN_TOP);
txt[i] = new GuiText("Coding & menu design");
txt[i]->SetPosition(40,y); i++;
txt[i]->SetPosition(60,y); i++;
txt[i] = new GuiText("Tantric");
txt[i]->SetPosition(335,y); i++; y+=24;
txt[i]->SetPosition(350,y); i++; y+=24;
txt[i] = new GuiText("Coding");
txt[i]->SetPosition(40,y); i++;
txt[i]->SetPosition(60,y); i++;
txt[i] = new GuiText("michniewski");
txt[i]->SetPosition(335,y); i++; y+=24;
txt[i]->SetPosition(350,y); i++; y+=24;
txt[i] = new GuiText("Menu artwork");
txt[i]->SetPosition(40,y); i++;
txt[i]->SetPosition(60,y); i++;
txt[i] = new GuiText("the3seashells");
txt[i]->SetPosition(335,y); i++; y+=24;
txt[i]->SetPosition(350,y); i++; y+=24;
txt[i] = new GuiText("Menu sound");
txt[i]->SetPosition(40,y); i++;
txt[i]->SetPosition(60,y); i++;
txt[i] = new GuiText("Peter de Man");
txt[i]->SetPosition(335,y); i++; y+=48;
txt[i]->SetPosition(350,y); i++; y+=48;
txt[i] = new GuiText("Snes9x GX GameCube");
txt[i]->SetPosition(40,y); i++;
txt[i]->SetPosition(60,y); i++;
txt[i] = new GuiText("SoftDev, crunchy2,");
txt[i]->SetPosition(335,y); i++; y+=24;
txt[i]->SetPosition(350,y); i++; y+=24;
txt[i] = new GuiText("eke-eke, others");
txt[i]->SetPosition(335,y); i++; y+=24;
txt[i]->SetPosition(350,y); i++; y+=24;
txt[i] = new GuiText("Snes9x");
txt[i]->SetPosition(40,y); i++;
txt[i]->SetPosition(60,y); i++;
txt[i] = new GuiText("Snes9x Team");
txt[i]->SetPosition(335,y); i++; y+=24;
txt[i]->SetPosition(350,y); i++; y+=24;
txt[i] = new GuiText("libogc / devkitPPC");
txt[i]->SetPosition(40,y); i++;
txt[i]->SetPosition(60,y); i++;
txt[i] = new GuiText("shagkur & wintermute");
txt[i]->SetPosition(335,y); i++; y+=24;
txt[i]->SetPosition(350,y); i++; y+=24;
txt[i] = new GuiText("FreeTypeGX");
txt[i]->SetPosition(40,y); i++;
txt[i]->SetPosition(60,y); i++;
txt[i] = new GuiText("Armin Tamzarian");
txt[i]->SetPosition(335,y); i++; y+=48;
txt[i]->SetPosition(350,y); i++; y+=48;
txt[i]->SetPresets(18, (GXColor){0, 0, 0, 255}, 0,
FTGX_JUSTIFY_CENTER | FTGX_ALIGN_TOP, ALIGN_CENTRE, ALIGN_TOP);
@ -3724,7 +3724,7 @@ static int MenuSettingsNetwork()
GuiOptionBrowser optionBrowser(552, 248, &options);
optionBrowser.SetPosition(0, 108);
optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
optionBrowser.SetCol2Position(275);
optionBrowser.SetCol2Position(290);
HaltGui();
GuiWindow w(screenwidth, screenheight);

View File

@ -1,31 +1,41 @@
/********************************************************************************************
PNGU Version : 0.2a
Coder : frontier
More info : http://frontier-dev.net
Modified by Tantric, 2009
*
* PNGU
*
* Original author: frontier (http://frontier-dev.net)
* Modified by Tantric, 2009-2010
*
********************************************************************************************/
#include <stdio.h>
#include <malloc.h>
#include <gccore.h>
#include "pngu.h"
#include "png.h"
#include <png.h>
// Constants
#define PNGU_SOURCE_BUFFER 1
#define PNGU_SOURCE_DEVICE 2
#define PNGU_SOURCE_BUFFER 1
#define PNGU_SOURCE_DEVICE 2
// Prototypes of helper functions
int pngu_info (IMGCTX ctx);
int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha);
void pngu_free_info (IMGCTX ctx);
void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length);
void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length);
void pngu_flush_data_to_buffer (png_structp png_ptr);
int pngu_clamp (int value, int min, int max);
// Return codes
#define PNGU_OK 0
#define PNGU_ODD_WIDTH 1
#define PNGU_ODD_STRIDE 2
#define PNGU_INVALID_WIDTH_OR_HEIGHT 3
#define PNGU_FILE_IS_NOT_PNG 4
#define PNGU_UNSUPPORTED_COLOR_TYPE 5
#define PNGU_NO_FILE_SELECTED 6
#define PNGU_CANT_OPEN_FILE 7
#define PNGU_CANT_READ_FILE 8
#define PNGU_LIB_ERROR 9
// Color types
#define PNGU_COLOR_TYPE_GRAY 1
#define PNGU_COLOR_TYPE_GRAY_ALPHA 2
#define PNGU_COLOR_TYPE_PALETTE 3
#define PNGU_COLOR_TYPE_RGB 4
#define PNGU_COLOR_TYPE_RGB_ALPHA 5
#define PNGU_COLOR_TYPE_UNKNOWN 6
// PNGU Image context struct
struct _IMGCTX
@ -49,362 +59,42 @@ struct _IMGCTX
// PNGU Implementation
IMGCTX PNGU_SelectImageFromBuffer (const void *buffer)
static void pngu_free_info (IMGCTX ctx)
{
IMGCTX ctx = NULL;
if (!buffer)
return NULL;
ctx = malloc (sizeof (struct _IMGCTX));
if (!ctx)
return NULL;
ctx->buffer = (void *) buffer;
ctx->source = PNGU_SOURCE_BUFFER;
ctx->cursor = 0;
ctx->filename = NULL;
ctx->propRead = 0;
ctx->infoRead = 0;
return ctx;
}
IMGCTX PNGU_SelectImageFromDevice (const char *filename)
{
IMGCTX ctx = NULL;
if (!filename)
return NULL;
ctx = malloc (sizeof (struct _IMGCTX));
if (!ctx)
return NULL;
ctx->buffer = NULL;
ctx->source = PNGU_SOURCE_DEVICE;
ctx->cursor = 0;
ctx->filename = malloc (strlen (filename) + 1);
if (!ctx->filename)
{
free (ctx);
return NULL;
}
strcpy(ctx->filename, filename);
ctx->propRead = 0;
ctx->infoRead = 0;
return ctx;
}
void PNGU_ReleaseImageContext (IMGCTX ctx)
{
if (!ctx)
return;
if (ctx->filename)
free (ctx->filename);
if ((ctx->propRead) && (ctx->prop.trans))
free (ctx->prop.trans);
pngu_free_info (ctx);
free (ctx);
}
int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *imgprop)
{
int res;
if (!ctx->propRead)
{
res = pngu_info (ctx);
if (res != PNGU_OK)
return res;
}
*imgprop = ctx->prop;
return PNGU_OK;
}
int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha)
{
int result;
PNGU_u32 x, y, qwidth, qheight;
PNGU_u64 alphaMask;
// width and height need to be divisible by four
if ((width % 4) || (height % 4))
return PNGU_INVALID_WIDTH_OR_HEIGHT;
result = pngu_decode (ctx, width, height, 0);
if (result != PNGU_OK)
return result;
// Init some variables
qwidth = width >> 2;
qheight = height >> 2;
// Check is source image has an alpha channel
if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) )
{
// Alpha channel present, copy image to the output buffer
for (y = 0; y < qheight; y++)
for (x = 0; x < qwidth; x++)
{
int blockbase = (y * qwidth + x) << 3;
PNGU_u32 y4 = y << 2;
PNGU_u32 x16 = x << 4;
PNGU_u64 fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4]+x16));
PNGU_u64 fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4]+x16+8));
((PNGU_u64 *) buffer)[blockbase] =
((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
((PNGU_u64 *) buffer)[blockbase+4] =
((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4+1]+x16));
fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4+1]+x16+8));
((PNGU_u64 *) buffer)[blockbase+1] =
((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
((PNGU_u64 *) buffer)[blockbase+5] =
((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4+2]+x16));
fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4+2]+x16+8));
((PNGU_u64 *) buffer)[blockbase+2] =
((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
((PNGU_u64 *) buffer)[blockbase+6] =
((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4+3]+x16));
fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4+3]+x16+8));
((PNGU_u64 *) buffer)[blockbase+3] =
((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
((PNGU_u64 *) buffer)[blockbase+7] =
((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
}
}
else
{
// No alpha channel present, copy image to the output buffer
alphaMask = (((PNGU_u64)default_alpha) << 56) | (((PNGU_u64)default_alpha) << 40) |
(((PNGU_u64)default_alpha) << 24) | (((PNGU_u64)default_alpha) << 8);
for (y = 0; y < qheight; y++)
for (x = 0; x < qwidth; x++)
{
int blockbase = (y * qwidth + x) << 3;
PNGU_u32 y4 = y << 2;
PNGU_u32 x12 = x * 12;
PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y4]+x12));
PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4]+x12+8));
((PNGU_u64 *) buffer)[blockbase] =
(((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
((PNGU_u64 *) buffer)[blockbase+4] =
(((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+1]+x12));
field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+1]+x12+8));
((PNGU_u64 *) buffer)[blockbase+1] =
(((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
((PNGU_u64 *) buffer)[blockbase+5] =
(((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+2]+x12));
field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+2]+x12+8));
((PNGU_u64 *) buffer)[blockbase+2] =
(((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
((PNGU_u64 *) buffer)[blockbase+6] =
(((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+3]+x12));
field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+3]+x12+8));
((PNGU_u64 *) buffer)[blockbase+3] =
(((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
((PNGU_u64 *) buffer)[blockbase+7] =
(((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
}
}
// Free resources
free (ctx->img_data);
free (ctx->row_pointers);
// Success
return PNGU_OK;
}
int PNGU_EncodeFromRGB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
{
png_uint_32 rowbytes;
PNGU_u32 y;
// Erase from the context any readed info
pngu_free_info (ctx);
ctx->propRead = 0;
// Check if the user has selected a file to write the image
if (ctx->source == PNGU_SOURCE_BUFFER);
else if (ctx->source == PNGU_SOURCE_DEVICE)
{
// Open file
if (!(ctx->fd = fopen (ctx->filename, "wb")))
return PNGU_CANT_OPEN_FILE;
}
else
return PNGU_NO_FILE_SELECTED;
// Allocation of libpng structs
ctx->png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!(ctx->png_ptr))
if (ctx->infoRead)
{
if (ctx->source == PNGU_SOURCE_DEVICE)
fclose (ctx->fd);
return PNGU_LIB_ERROR;
png_destroy_read_struct (&(ctx->png_ptr), &(ctx->info_ptr), (png_infopp)NULL);
ctx->infoRead = 0;
}
ctx->info_ptr = png_create_info_struct (ctx->png_ptr);
if (!(ctx->info_ptr))
{
png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
if (ctx->source == PNGU_SOURCE_DEVICE)
fclose (ctx->fd);
return PNGU_LIB_ERROR;
}
if (ctx->source == PNGU_SOURCE_BUFFER)
{
// Installation of our custom data writer function
ctx->cursor = 0;
png_set_write_fn (ctx->png_ptr, ctx, pngu_write_data_to_buffer, pngu_flush_data_to_buffer);
}
else if (ctx->source == PNGU_SOURCE_DEVICE)
{
// Default data writer uses function fwrite, so it needs to use our FILE*
png_init_io (ctx->png_ptr, ctx->fd);
}
// Setup output file properties
png_set_IHDR (ctx->png_ptr, ctx->info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
// Allocate memory to store the image in RGB format
rowbytes = width * 3;
if (rowbytes % 4)
rowbytes = ((rowbytes >>2) + 1) <<2; // Add extra padding so each row starts in a 4 byte boundary
ctx->img_data = malloc(rowbytes * height);
memset(ctx->img_data, 0, rowbytes * height);
if (!ctx->img_data)
{
png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
if (ctx->source == PNGU_SOURCE_DEVICE)
fclose (ctx->fd);
return PNGU_LIB_ERROR;
}
ctx->row_pointers = malloc (sizeof (png_bytep) * height);
memset(ctx->row_pointers, 0, sizeof (png_bytep) * height);
if (!ctx->row_pointers)
{
png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
if (ctx->source == PNGU_SOURCE_DEVICE)
fclose (ctx->fd);
return PNGU_LIB_ERROR;
}
for (y = 0; y < height; ++y)
{
ctx->row_pointers[y] = buffer + (y * rowbytes);
}
// Tell libpng where is our image data
png_set_rows (ctx->png_ptr, ctx->info_ptr, ctx->row_pointers);
// Write file header and image data
png_write_png (ctx->png_ptr, ctx->info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
// Tell libpng we have no more data to write
png_write_end (ctx->png_ptr, (png_infop) NULL);
// Free resources
free (ctx->img_data);
free (ctx->row_pointers);
png_destroy_write_struct (&(ctx->png_ptr), &(ctx->info_ptr));
if (ctx->source == PNGU_SOURCE_DEVICE)
fclose (ctx->fd);
// Success
return ctx->cursor;
}
int PNGU_EncodeFromGXTexture (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
// Custom data provider function used for reading from memory buffers.
static void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length)
{
int res;
PNGU_u32 x,y, tmpy1, tmpy2, tmpyWid, tmpxy;
unsigned char * ptr = (unsigned char*)buffer;
unsigned char * tmpbuffer = (unsigned char *)malloc(width*height*3);
memset(tmpbuffer, 0, width*height*3);
png_uint_32 offset;
for(y=0; y < height; y++)
{
tmpy1 = y * 640*3;
tmpy2 = y%4 << 2;
tmpyWid = (((y >> 2)<<4)*width);
for(x=0; x < width; x++)
{
offset = tmpyWid + ((x >> 2)<<6) + ((tmpy2+ x%4 ) << 1);
tmpxy = x * 3 + tmpy1;
tmpbuffer[tmpxy ] = ptr[offset+1]; // R
tmpbuffer[tmpxy+1] = ptr[offset+32]; // G
tmpbuffer[tmpxy+2] = ptr[offset+33]; // B
}
}
res = PNGU_EncodeFromRGB (ctx, width, height, tmpbuffer, stride);
free(tmpbuffer);
return res;
IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr);
memcpy (data, ctx->buffer + ctx->cursor, length);
ctx->cursor += length;
}
int pngu_info (IMGCTX ctx)
// Custom data writer function used for writing to memory buffers.
static void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length)
{
IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr);
memcpy (ctx->buffer + ctx->cursor, data, length);
ctx->cursor += length;
}
// Custom data flusher function used for writing to memory buffers.
static void pngu_flush_data_to_buffer (png_structp png_ptr)
{
// Nothing to do here
}
static int pngu_info (IMGCTX ctx)
{
png_byte magic[8];
png_uint_32 width;
@ -604,7 +294,7 @@ int pngu_info (IMGCTX ctx)
return PNGU_OK;
}
int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha)
static int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha)
{
png_uint_32 rowbytes;
png_uint_32 i, propImgHeight;
@ -679,48 +369,313 @@ int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlph
return PNGU_OK;
}
void pngu_free_info (IMGCTX ctx)
static inline PNGU_u32 coordsRGBA8(PNGU_u32 x, PNGU_u32 y, PNGU_u32 w)
{
if (ctx->infoRead)
return ((((y >> 2) * (w >> 2) + (x >> 2)) << 5) + ((y & 3) << 2) + (x & 3)) << 1;
}
static PNGU_u8 * PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u8 default_alpha)
{
PNGU_u8 *dst;
PNGU_u32 x, y, offset;
png_byte *pixel;
if (pngu_decode (ctx, width, height, 0) != PNGU_OK)
return NULL;
PNGU_u32 newWidth = width;
if(newWidth%4) newWidth += (4-newWidth%4);
PNGU_u32 newHeight = height;
if(newHeight%4) newHeight += (4-newHeight%4);
int len = (newWidth * newHeight) << 2;
if(len%32) len += (32-len%32);
dst = memalign (32, len);
if(!dst)
return NULL;
for (y = 0; y < newHeight; y++)
{
for (x = 0; x < newWidth; x++)
{
offset = coordsRGBA8(x, y, newWidth);
if(y >= height || x >= width)
{
dst[offset] = 0;
dst[offset+1] = 255;
dst[offset+32] = 255;
dst[offset+33] = 255;
}
else
{
if (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA ||
ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA)
{
pixel = &(ctx->row_pointers[y][x*4]);
dst[offset] = pixel[3]; // Alpha
dst[offset+1] = pixel[0]; // Red
dst[offset+32] = pixel[1]; // Green
dst[offset+33] = pixel[2]; // Blue
}
else
{
pixel = &(ctx->row_pointers[y][x*3]);
dst[offset] = default_alpha; // Alpha
dst[offset+1] = pixel[0]; // Red
dst[offset+32] = pixel[1]; // Green
dst[offset+33] = pixel[2]; // Blue
}
}
}
}
// Free resources
free (ctx->img_data);
free (ctx->row_pointers);
DCFlushRange(dst, len);
return dst;
}
IMGCTX PNGU_SelectImageFromBuffer (const void *buffer)
{
IMGCTX ctx = NULL;
if (!buffer)
return NULL;
ctx = malloc (sizeof (struct _IMGCTX));
if (!ctx)
return NULL;
ctx->buffer = (void *) buffer;
ctx->source = PNGU_SOURCE_BUFFER;
ctx->cursor = 0;
ctx->filename = NULL;
ctx->propRead = 0;
ctx->infoRead = 0;
return ctx;
}
IMGCTX PNGU_SelectImageFromDevice (const char *filename)
{
IMGCTX ctx = NULL;
if (!filename)
return NULL;
ctx = malloc (sizeof (struct _IMGCTX));
if (!ctx)
return NULL;
ctx->buffer = NULL;
ctx->source = PNGU_SOURCE_DEVICE;
ctx->cursor = 0;
ctx->filename = malloc (strlen (filename) + 1);
if (!ctx->filename)
{
free (ctx);
return NULL;
}
strcpy(ctx->filename, filename);
ctx->propRead = 0;
ctx->infoRead = 0;
return ctx;
}
void PNGU_ReleaseImageContext (IMGCTX ctx)
{
if (!ctx)
return;
if (ctx->filename)
free (ctx->filename);
if ((ctx->propRead) && (ctx->prop.trans))
free (ctx->prop.trans);
pngu_free_info (ctx);
free (ctx);
}
int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *imgprop)
{
int res;
if (!ctx->propRead)
{
res = pngu_info (ctx);
if (res != PNGU_OK)
return res;
}
*imgprop = ctx->prop;
return PNGU_OK;
}
PNGU_u8 * DecodePNG(const PNGU_u8 *src, int * width, int * height)
{
PNGUPROP imgProp;
IMGCTX ctx = PNGU_SelectImageFromBuffer(src);
PNGU_u8 *dst = NULL;
if(!ctx)
return NULL;
if(PNGU_GetImageProperties(ctx, &imgProp) == PNGU_OK)
{
dst = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, 255);
*width = imgProp.imgWidth;
*height = imgProp.imgHeight;
}
PNGU_ReleaseImageContext (ctx);
return dst;
}
int PNGU_EncodeFromRGB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
{
png_uint_32 rowbytes;
PNGU_u32 y;
// Erase from the context any readed info
pngu_free_info (ctx);
ctx->propRead = 0;
// Check if the user has selected a file to write the image
if (ctx->source == PNGU_SOURCE_BUFFER);
else if (ctx->source == PNGU_SOURCE_DEVICE)
{
// Open file
if (!(ctx->fd = fopen (ctx->filename, "wb")))
return PNGU_CANT_OPEN_FILE;
}
else
return PNGU_NO_FILE_SELECTED;
// Allocation of libpng structs
ctx->png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!(ctx->png_ptr))
{
if (ctx->source == PNGU_SOURCE_DEVICE)
fclose (ctx->fd);
png_destroy_read_struct (&(ctx->png_ptr), &(ctx->info_ptr), (png_infopp)NULL);
ctx->infoRead = 0;
return PNGU_LIB_ERROR;
}
ctx->info_ptr = png_create_info_struct (ctx->png_ptr);
if (!(ctx->info_ptr))
{
png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
if (ctx->source == PNGU_SOURCE_DEVICE)
fclose (ctx->fd);
return PNGU_LIB_ERROR;
}
if (ctx->source == PNGU_SOURCE_BUFFER)
{
// Installation of our custom data writer function
ctx->cursor = 0;
png_set_write_fn (ctx->png_ptr, ctx, pngu_write_data_to_buffer, pngu_flush_data_to_buffer);
}
else if (ctx->source == PNGU_SOURCE_DEVICE)
{
// Default data writer uses function fwrite, so it needs to use our FILE*
png_init_io (ctx->png_ptr, ctx->fd);
}
// Setup output file properties
png_set_IHDR (ctx->png_ptr, ctx->info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
// Allocate memory to store the image in RGB format
rowbytes = width * 3;
if (rowbytes % 4)
rowbytes = ((rowbytes >>2) + 1) <<2; // Add extra padding so each row starts in a 4 byte boundary
ctx->img_data = malloc(rowbytes * height);
memset(ctx->img_data, 0, rowbytes * height);
if (!ctx->img_data)
{
png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
if (ctx->source == PNGU_SOURCE_DEVICE)
fclose (ctx->fd);
return PNGU_LIB_ERROR;
}
ctx->row_pointers = malloc (sizeof (png_bytep) * height);
memset(ctx->row_pointers, 0, sizeof (png_bytep) * height);
if (!ctx->row_pointers)
{
png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
if (ctx->source == PNGU_SOURCE_DEVICE)
fclose (ctx->fd);
return PNGU_LIB_ERROR;
}
for (y = 0; y < height; ++y)
{
ctx->row_pointers[y] = buffer + (y * rowbytes);
}
// Tell libpng where is our image data
png_set_rows (ctx->png_ptr, ctx->info_ptr, ctx->row_pointers);
// Write file header and image data
png_write_png (ctx->png_ptr, ctx->info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
// Tell libpng we have no more data to write
png_write_end (ctx->png_ptr, (png_infop) NULL);
// Free resources
free (ctx->img_data);
free (ctx->row_pointers);
png_destroy_write_struct (&(ctx->png_ptr), &(ctx->info_ptr));
if (ctx->source == PNGU_SOURCE_DEVICE)
fclose (ctx->fd);
// Success
return ctx->cursor;
}
// Custom data provider function used for reading from memory buffers.
void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length)
int PNGU_EncodeFromGXTexture (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
{
IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr);
memcpy (data, ctx->buffer + ctx->cursor, length);
ctx->cursor += length;
}
int res;
PNGU_u32 x,y, tmpy1, tmpy2, tmpyWid, tmpxy;
// Custom data writer function used for writing to memory buffers.
void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length)
{
IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr);
memcpy (ctx->buffer + ctx->cursor, data, length);
ctx->cursor += length;
}
unsigned char * ptr = (unsigned char*)buffer;
unsigned char * tmpbuffer = (unsigned char *)malloc(width*height*3);
memset(tmpbuffer, 0, width*height*3);
png_uint_32 offset;
for(y=0; y < height; y++)
{
tmpy1 = y * 640*3;
tmpy2 = y%4 << 2;
tmpyWid = (((y >> 2)<<4)*width);
// Custom data flusher function used for writing to memory buffers.
void pngu_flush_data_to_buffer (png_structp png_ptr)
{
// Nothing to do here
}
for(x=0; x < width; x++)
{
offset = tmpyWid + ((x >> 2)<<6) + ((tmpy2+ x%4 ) << 1);
tmpxy = x * 3 + tmpy1;
// Function used in YCbYCr to RGB decoding
int pngu_clamp (int value, int min, int max)
{
if (value < min)
value = min;
else if (value > max)
value = max;
return value;
tmpbuffer[tmpxy ] = ptr[offset+1]; // R
tmpbuffer[tmpxy+1] = ptr[offset+32]; // G
tmpbuffer[tmpxy+2] = ptr[offset+33]; // B
}
}
res = PNGU_EncodeFromRGB (ctx, width, height, tmpbuffer, stride);
free(tmpbuffer);
return res;
}

View File

@ -1,38 +1,15 @@
/********************************************************************************************
PNGU Version : 0.2a
Coder : frontier
More info : http://frontier-dev.net
Modified by Tantric, 2009
*
* PNGU
*
* Original author: frontier (http://frontier-dev.net)
* Modified by Tantric, 2009-2010
*
********************************************************************************************/
#ifndef __PNGU__
#define __PNGU__
// Return codes
#define PNGU_OK 0
#define PNGU_ODD_WIDTH 1
#define PNGU_ODD_STRIDE 2
#define PNGU_INVALID_WIDTH_OR_HEIGHT 3
#define PNGU_FILE_IS_NOT_PNG 4
#define PNGU_UNSUPPORTED_COLOR_TYPE 5
#define PNGU_NO_FILE_SELECTED 6
#define PNGU_CANT_OPEN_FILE 7
#define PNGU_CANT_READ_FILE 8
#define PNGU_LIB_ERROR 9
// Color types
#define PNGU_COLOR_TYPE_GRAY 1
#define PNGU_COLOR_TYPE_GRAY_ALPHA 2
#define PNGU_COLOR_TYPE_PALETTE 3
#define PNGU_COLOR_TYPE_RGB 4
#define PNGU_COLOR_TYPE_RGB_ALPHA 5
#define PNGU_COLOR_TYPE_UNKNOWN 6
#ifdef __cplusplus
extern "C" {
#endif
@ -67,7 +44,7 @@ struct _IMGCTX;
typedef struct _IMGCTX *IMGCTX;
/****************************************************************************
* Image context handling *
* Image context handling *
****************************************************************************/
// Selects a PNG file, previosly loaded into a buffer, and creates an image context for subsequent procesing.
@ -79,22 +56,18 @@ IMGCTX PNGU_SelectImageFromDevice (const char *filename);
// Frees resources associated with an image context. Always call this function when you no longer need the IMGCTX.
void PNGU_ReleaseImageContext (IMGCTX ctx);
/****************************************************************************
* Miscelaneous *
* Miscellaneous *
****************************************************************************/
// Retrieves info from selected PNG file, including image dimensions, color format, background and transparency colors.
int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *fileproperties);
/****************************************************************************
* Image conversion *
* Image conversion *
****************************************************************************/
// Expands selected image into a 4x4 tiled RGBA8 buffer. You need to specify context, image dimensions,
// destination address and default alpha value, which is used if the source image doesn't have an alpha channel.
int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha);
PNGU_u8 * DecodePNG(const PNGU_u8 *src, int *width, int *height);
int PNGU_EncodeFromRGB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
int PNGU_EncodeFromGXTexture (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
@ -103,4 +76,3 @@ int PNGU_EncodeFromGXTexture (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void
#endif
#endif