Demoscene.fr BBS

Articles et discussions techniques => Code => Topic started by: azerty on 18 May 2011 à 14:34:58

Title: Données dans exe
Post by: azerty on 18 May 2011 à 14:34:58
Bonjour,

Je dois inclure des images et musiques dans un exe; sachant que celles-ci sont assez conséquentes, je voudrais avoir des infos sur la manière de procéder soit avec GCC (C::B) soit avec Visual C++.
Je sais qu'il y a les ressources sous VC, mais je ne sais pas si c'est la bonne méthode...

Merci d'avance pour vos conseils,
azerty
Title: Re : Données dans exe
Post by: maracuja on 18 May 2011 à 14:55:20
Bonjour,

Pour faire simple, il existe deux formats d'executable, ceux fonctionnant sous linux, (les fichiers elf) et ceux sous windows (les fichiers pe).
Les fichiers PE permettent aisément d'avoir un espace au sein du fichier executable nommé section.
La section resource  est un espace "fourre-tout".
C'est une solution simple, élégante et facile a mettre en oeuvre.

L'autre solution "générique" est de convertir ton fichier binaire (mp3, xm, que sais-je) en un tableau exploitable par ton programme.

Ceci étant dit, il existe un article  traitant de la création d'une pseudo section resouce avec un fichier au format ELF [1]. Tu noteras que les exemples sont pour SDL mais c'est facilement transposable.



[1] http://www.xgarreau.org/aide/devel/sdl/rwops.php (http://www.xgarreau.org/aide/devel/sdl/rwops.php)
Title: Re : Données dans exe
Post by: azerty on 18 May 2011 à 15:14:58
Bonjour maracuja,

Merci pour ta réponse rapide. Je suis en train de lire l'article; je devrais m'en sortir avec ça...

azerty
Title: Re : Données dans exe
Post by: LLB on 18 May 2011 à 15:32:35
Pour les intros 64k, j'ai vu deux techniques :

- Les outils du genre bin2c (http://homepage.ntlworld.com/rik.griffin/bin2c.html), bin2h (http://www.deadnode.org/sw/bin2h/). C'est super simple à utiliser, mais ce n'est pas adapté pour les grosses données.

- Utiliser un fichier assembleur qui se contente de faire incbin du fichier. C'est ce que j'utilise et j'aime bien cette méthode. Il faut modifier un peu le build system pour appeler un assembleur. Quelques infos sur pouet (http://pouet.net/topic.php?which=6082&page=1). Si tu télécharges v2 (http://www.1337haxorz.de/products.html), tu peux voir comment c'est intégré dans VS dans leur exemple.

Ensuite, la méthode plus standard est d'utiliser les ressources, je ne sais pas si ça peut se faire de façon portable.

Si tes données font plusieurs Mo, je te conseille plutôt de ne pas les mettre dans le fichier exécutable (utilise un fichier à part).
Title: Re : Données dans exe
Post by: nystep on 18 May 2011 à 15:43:17
sous nasm, tu peux utiliser la commande incbin pour inclure tout un fichier binaire et stocker un label de début, un label de fin, la différence des deux te donne la taille des données..
Title: Re : Données dans exe
Post by: flure on 18 May 2011 à 16:00:04
Pour des petits fichiers, la méthode la plus simple et portable est quand même celle du "bin2c", en plus si tu ne disposes pas de l'outil pour ça, c'est extrêmement trivial à coder (en python par exemple, c'est une 20aine de lignes de code).

Je ne sais pas ce que les ressources apportent de plus pour les gros fichiers, à part un peu de propreté dans l'environnement de dev... Ou alors elles ne sont pas chargées en même temps que le code exécutable ?
Title: Re : Données dans exe
Post by: azerty on 18 May 2011 à 16:09:05
Bonjour LLB,

- Utiliser un fichier assembleur qui se contente de faire incbin du fichier. C'est ce que j'utilise et j'aime bien cette méthode. Il faut modifier un peu le build system pour appeler un assembleur. Quelques infos sur pouet (http://pouet.net/topic.php?which=6082&page=1). Si tu télécharges v2 (http://www.1337haxorz.de/products.html), tu peux voir comment c'est intégré dans VS dans leur exemple.

Je ne sais encore si la prod devra être portable ou pas, mais je trouve cette méthode ASM des plus simples. Si j'utilise VS, j'opterai pour cette solution. Merci pour l'info!

Si tes données font plusieurs Mo, je te conseille plutôt de ne pas les mettre dans le fichier exécutable (utilise un fichier à part).

Je dois encore discuter de cela avec le concepteur. Je lui soumettrai cette remarque. Quand tu dis, fichier à part, tu penses à des fichiers séparés
ou à un pak?

Personnellement, cacher les données n'est pas quelque chose qui me semble si important, mais bon... si c'est ce que le roi veut :)

Encore merci!


azerty
Title: Re : Données dans exe
Post by: nystep on 18 May 2011 à 16:18:30
Quote
Je dois encore discuter de cela avec le concepteur. Je lui soumettrai cette remarque.

Et donc peux-tu dire sur quel type de projet tu travailles? ;) une démo?
Title: Re : Re : Données dans exe
Post by: LLB on 18 May 2011 à 16:28:46
Je ne sais encore si la prod devra être portable ou pas, mais je trouve cette méthode ASM des plus simples. Si j'utilise VS, j'opterai pour cette solution. Merci pour l'info!
Si tu utilises un Makefile, c'est facile aussi de lui dire comment compiler le fichier assembleur (quand tu appelles nasm ou autre, tu obtiens un fichier .o/.obj).

Quand tu dis, fichier à part, tu penses à des fichiers séparés ou à un pak?
L'un ou l'autre. Si c'est une musique mp3/ogg, tu peux la laisser à part, je trouve ça plus pratique (aussi bien pendant le dév, pouvoir modifier la musique sans recompiler, que pour l'utilisateur final). Si tu as peur qu'on te pique tes données, tu peux tout regrouper en un seul fichier (bon, ce n'est pas vraiment une protection, mais ça cache un peu).
Title: Re : Données dans exe
Post by: azerty on 18 May 2011 à 17:54:27
Et donc peux-tu dire sur quel type de projet tu travailles? ;) une démo?

Pas encore... Je laisse à l'initiateur du projet le soin d'annoncer la prod quand bon lui semblera ;)

Title: Re : Données dans exe
Post by: ok3anos on 18 May 2011 à 21:06:02
Hmmmm.... On se connait azerty ? ;)

Concernant les fichiers .pak je m'interroge sur comment les créer et comment accéder aux données?
 Est-ce un fichier de binaires compilées/empilées?
Quelqu'un pourrait-il m'orienter?

Concernant les ziks et les graphs, j'ai déjà fait ça en incluant tout dans un fichier resources mais ce n'est utile que pour une prod ne dépassant pas 2 Mo après, mieux vaut externaliser les données. Plus pratique, plus facile à gérer et les exes "trop lourds" ce n'est pas le top.... En plus quel est vraiment l'intérêt, sachant qu'on peut de toute façon facilement hacker les données.
Title: Re : Données dans exe
Post by: RaHoW on 18 May 2011 à 21:14:02
Okeanos: l’intérêt c'est d'avoir un seul fichier ^^ Ça m’intéresse énormément, parce que même en faisant un incbin ou un tableau binaire, je ne vois pas trop comment "simuler" le fait de charger le fichier (autant je peux peut être modifié mon code, autant loader une track en miniFmod ou quoi de cette manière... je vois pas comment faire)...

Il me restera plus qu'un bon timer et hop ^^
Title: Re : Re : Données dans exe
Post by: ok3anos on 18 May 2011 à 21:28:23
Okeanos: l’intérêt c'est d'avoir un seul fichier ^^ Ça m’intéresse énormément, parce que même en faisant un incbin ou un tableau binaire, je ne vois pas trop comment "simuler" le fait de charger le fichier (autant je peux peut être modifié mon code, autant loader une track en miniFmod ou quoi de cette manière... je vois pas comment faire)...

Il me restera plus qu'un bon timer et hop ^^

Alors quel est l'intérêt d'avoir un seul fichier ?

Si les fichiers sont inclus dans l'exe, il n'y a pas de chargement du fichier a proprement parler....... Tu les récupères juste en mémoire. Plus tu auras de fichiers inclus... plus l'exe mettra du temps a s'éxécuter. D'où l'intérêt de ne pas avoir des exes trop lourds.........

Idem pour minifmod.
Concernant minifmod c'est très simple, tu inclus plusieurs fichiers xm dans la resource et tu les appelle au moment voulu.

les fichiers externalisés sont mieux à mon avis. Sauf dans le cas d'une 64k bien sûr.
Title: Re : Données dans exe
Post by: RaHoW on 18 May 2011 à 21:37:42
C'est aussi histoire de pouvoir avoir un seul fichier ressource packer... ça et en 64k ça m’intéresse de toutes manières de savoir le faire.

Quand au fait de "récupérer juste en mémoire" j'ai l'impression que c'est pas si simple... je peux pas juste balancer mon tableau de datas dans un pointeur non?? Je suis forcement obliger de "shunter" le loader si y en a un??
Title: Re : Données dans exe
Post by: ok3anos on 18 May 2011 à 21:53:40
La récup se fait juste par un FindResource et un LoadResource.
Tu as des tonnes d'exemples là dessus.

Mais pour les 64kb ce ne sont pas ses méthodes qui sont retenues. Pour la zik se sont les synths et pour les graphs c'est pratiquement que du procedural + shaders.
Je me suis beaucoup intéressé aux 64k pour le procedural. Toutes mes particules sont générées comme ça parce que c'est pratique.
Après, à cause du boulot et de la vie de famille je n'ai pas le temps et l'énergie nécessaire pour m'investir à fond là-dedans. On en discutait avec Ulrich/FRequency à la REVISION, ça demande un investissement considérable en temps et en énergie. Créer son framework seul c'est pas évident (surtout quand on est pas codeur à la base).
Title: Re : Données dans exe
Post by: xoofx on 18 May 2011 à 22:07:41
Comme cela a été dit, les bin2h, les links avec nasm, les archives externes sont des bons candidats... Je ne partirais pas trop en revanche sur une solution resource windows.

Mais ce qui est surtout important dans cette histoire de chargement des données, c'est de développer une API qui fasse abstraction de la source des données (filesystem, archive, socket...etc). Normalement, tout chargement de data doit ensuite passer par une telle API.

Côté utilisation, cela doit donner quelque chose du style:
Code: [Select]

// Init du AssetManager au début de l'appli
AssetManager assetManager = new AssetManagerFromXXX();

...

// Chargement d'une resource
assetManager.Load<Texture>("/images/mytexture.jpg");

AssetManager propose une interface de chargement pour laquelle on a plusieurs classes concrètes (AssetManagerFromZip, AssetManagerFromFS, ou même les deux combinés lorsque par exemple, on veut charger d'abord à partir du Zip, sinon à partir du FS).

Derrière, à chaque type d'asset, il y a un loader à partir d'un stream abstrait, que le loader soit une classe extérieure ou intégré à la classe de l'asset (TextureLoader ou Texture). L'AssetManager est sensé créer des stream en fonction du type de la source de données.

Bon, voila le principe en gros, après, il y a une variété d'implem! ;)
Title: Re : Données dans exe
Post by: Patapom on 18 May 2011 à 23:02:44
Mmmh... Moi ce que j'ai fait c'est simplement tout baser mes chargements sur le type System.IO.Stream, du coup pas besoin de faire d'asset manager.
Si tu charges du disque alors les streams sont des FileStreams, si tu charges d'une archive alors les streams sont des MemoryStreams...
Title: Re : Données dans exe
Post by: xoofx on 18 May 2011 à 23:16:33
Mmmh... Moi ce que j'ai fait c'est simplement tout baser mes chargements sur le type System.IO.Stream, du coup pas besoin de faire d'asset manager.
Si tu charges du disque alors les streams sont des FileStreams, si tu charges d'une archive alors les streams sont des MemoryStreams...
Oui oui, je passe aussi par un Stream abstrait (l'AssetManager utilise la classe Stream), mais je conseille d'avoir un endroit qui centralise les chargements, et qui encapsule le type de stockage. C'est l'asset manager, suivant sa config, qui fournit un Stream qui charge à partir d'un fichier, ou d'un zip...etc. Il ne faut pas que dans le code, il y ai une référence explicite au fait que le chargement se fait à partir d'un fichier du FS ou autre... enfin, tout ça, c'est à la condition que tu veux pouvoir rendre transparent le chargement à partir de n'importe quelle source sans changer ton code...
Title: Re : Données dans exe
Post by: Patapom on 19 May 2011 à 00:06:20
Bah oui justement : si tu passes pas un stream t'es dépendant de rien. Après derrière je construis in BinaryReader à partir de ce stream.
Le stream peut venir de n'importe quelle source, disque ou mémoire comme je disais.

L'asset manager c'est un + ouais mais c'est pas nécessaire. C'est même plutôt encombrant si tu veux supporter tous les types d'assets possibles...
Genre "Ah merde, j'ai oublié de faire une méthode pour charger une TPage qui prend en paramètre un array de textures et les tailles des sprites dans la TPage"... Cas hyper particulier, mais si t'es obligé de te le refarcir pour un manager à partir du disque, ou un manager à partir de la mémoire, ou manager qui fait du streaming ou je ne sais quoi encore... Ou alors j'ai pas compris l'intérêt de ton assets manager ? C'est toujours le même quelle que soit la source c'est ça ? Me suis gouré ?
Title: Re : Données dans exe
Post by: xoofx on 19 May 2011 à 10:40:00
Bah oui justement : si tu passes pas un stream t'es dépendant de rien. Après derrière je construis in BinaryReader à partir de ce stream.
Le stream peut venir de n'importe quelle source, disque ou mémoire comme je disais.
Le Stream est une étape, mais il te faut bien avoir une instanciation du stream. Si dans ton code, tu instancies directement des FileStream à chaque fois que tu veux charger un asset, et bien t'es parti pour devoir tout changer si tu veux charger à partir d'un zip ou autre.

Ce qu'il faut éviter, c'est ce genre de code
Code: [Select]
var mytexture = new Texture(new FileStream("./images/mytexture.jpg"));

mais le remplacer par un intermédiaire "StreamProvider" (qui derrière, peut charger à partir d'un zip, fs, socket...etc.):
Code: [Select]
var mytexture = new Texture(streamProvider.Find("./images/mytexture.jpg"));

L'AssetManager dans ce cas n'est qu'un intermédiaire supplémentaire par rapport à un "StreamProvider":

Code: [Select]
var mytexture = AssetManager.Load<Texture>("./images/mytexture.jpg");

Comme tu dis, il n'est pas absolument nécessaire, mais il permet de centraliser l'instanciation des Assets (et la manière dont il sont instanciés), de pouvoir affecter par exemple le nom du fichier directement à la texture, de pouvoir garder une liste des assets chargés, de pouvoir faire un cache d'objet...etc.

Aprés, en général, la quasi totalité des assets chargés sont en général des assets simples ( texture, mesh, musique...etc.). Le cas que tu décris nécessiterais, quelque soit la méthode de charger plusieurs assets simples pour les combiner ensemble.

Bon, comme je l'ai dit, l'important dans cette histoire, c'est d'avoir un code qui peut s'abstraire de la source de données et que la source puisse être changée en une ligne de code ou de config pour tout le reste de la démo.
Title: Re : Données dans exe
Post by: maracuja on 19 May 2011 à 11:35:23
Un decorator est une excellente solution pour charger des données.

En ce qui me concerne, j'évite au maximum d'utiliser les incbin pour charger des datas, car certes, c'est super pratique mais pas portable du tout. Entre les différents outils d'assemblages et architectures matérielles, c'est cauchemardesque  alors qu'un bon vieux bin2h n'a pas tous ces inconvénients.

Bon après c'est de la cuisine suivant les sensibilités de chacuns :=)
Title: Re : Données dans exe
Post by: xoofx on 19 May 2011 à 12:47:07
J'oubliais qu'il y a aussi une technique que j'utilise souvent pour packer des données avec un exe. C'est assez simple et portable: Je constitue une archive de fichiers (souvent dans un format propriétaire très simple: nombre de fichiers + liste de [taille du nom du fichier + nom du fichier + taille dans l'archive + data du fichier ] ) que j'ajoute à la fin de l'exe (par une simple concaténation binaire). Je rajoute juste à la fin de l'exe, la taille de l'archive (ou l'offset dans le fichier exe où l'archive est stocké, ce qui correspond à la taille de l'exe sans l'archive colée aux fesses) et un magic-number dans un entier pour être sûr que l'archive est bien présente. Tout ça s'automatise avec des simples scripts python, ruby, C# ou autres...
Ensuite, dans l'exe, il se recharge lui même en mémoire et vérifie la présence du magic-number à la fin, si oui, il fait pointer vers l'archive en mémoire, sinon, il la charge autrement (par le procédé décrit précédemment, via une archive externe, des répertoires...etc.).
Title: Re : Données dans exe
Post by: maracuja on 19 May 2011 à 13:26:20
tu fais comme x garreau grossomodo ? Par contre sur les OS recents (xp/vista/seven) cela fonctionne bien ce genre de chose ? Il n'y a pas de verification outre mesure quand il mappe le pe et les sections ?
Title: Re : Données dans exe
Post by: flure on 19 May 2011 à 13:51:07
Pas mal ta technique @lx, ça ressemble assez au système des ressources (ou à l'idée que je m'en fais).
Title: Re : Données dans exe
Post by: maracuja on 19 May 2011 à 14:08:08
Flure: Oui mais alors quel est l’intérêt de ne pas passer par le système de resource(s) d'un fichier PE vu que c'est "gratuit" ?
Title: Re : Données dans exe
Post by: flure on 19 May 2011 à 14:22:01
Maracuja : l'intérêt ? Ca marche sur tous les systèmes, et pas que Windows :)
Title: Re : Données dans exe
Post by: xoofx on 19 May 2011 à 14:41:21
tu fais comme x garreau grossomodo ? Par contre sur les OS recents (xp/vista/seven) cela fonctionne bien ce genre de chose ? Il n'y a pas de verification outre mesure quand il mappe le pe et les sections ?
xgarreau xgarreau... c ki ça?... ahhh ok ;D, J'avais pas vu le lien xgarreau! donc oui oui, c'est effectivement le même principe.

Sur Windows Vista/Seven, je n'ai jamais eu un seul problème avec cette méthode. Ca n'interfère pas avec le mapping des sections du PE en mémoire.

Flure: Oui mais alors quel est l’intérêt de ne pas passer par le système de resource(s) d'un fichier PE vu que c'est "gratuit" ?
Comme le souligne flure, c'est portable, ça permet même d'avoir un format plus compact que les ressources Windows classiques. Après, il y a un petit surcoût à développer le petit outil pour gérer l'outil de packing des ressources et le chargement de celle-ci, mais sinon, c'est plutôt raisonnable. In fine, le même système de chargement peut aussi être utilisé pour une archive externe, en utilisant exactement le même format de ficiher (signature à la fin du fichier...etc)
Title: Re : Données dans exe
Post by: maracuja on 19 May 2011 à 15:44:27
xgarreau xgarreau... c ki ça?... ahhh ok ;D, J'avais pas vu le lien xgarreau! donc oui oui, c'est effectivement le même principe.

Sur Windows Vista/Seven, je n'ai jamais eu un seul problème avec cette méthode. Ca n'interfère pas avec le mapping des sections du PE en mémoire.
Comme le souligne flure, c'est portable, ça permet même d'avoir un format plus compact que les ressources Windows classiques. Après, il y a un petit surcoût à développer le petit outil pour gérer l'outil de packing des ressources et le chargement de celle-ci, mais sinon, c'est plutôt raisonnable. In fine, le même système de chargement peut aussi être utilisé pour une archive externe, en utilisant exactement le même format de ficiher (signature à la fin du fichier...etc)

Alors pris la main dans le sac de ne pas suivre regarder mes liens !!! ;)

Ok, comme tu le précises, ce n'est pas énorme de coder cela au regard du reste  et qui plus est cela apporte une souplesse. :)

Par contre, on peut faire mieux qu'une structure arborescente. La section resource  en est une. Que peux t'on utiliser comme structure de données pour améliorer le stockage d'info ?
Title: Re : Données dans exe
Post by: nystep on 19 May 2011 à 18:33:39
Perso j'aime bien tout stocker dans un gros fichier .dat (données binaires) à coté de l'executable (maintenant, oui, je sais qu'en 2006 j'ai fait une démo sans aucune archive...). Celà signifie que si l'on veut distribuer sur plusieurs plateformes et bien pas besoin de faire un fichier executable de 40 mb pour chaque plateforme, le code tiendra amplement dans chaque executable de 1mb pour chaque plateforme, et les données dans un bon gros fichier .dat de 39mb.

Celà permet aussi de cacher un peu les choses pour les regards un peu trop indiscrets :) Mais c'est selon votre niveau de parano pour ça. On peut ajouter de la compression et du cryptage pour se faire plaisir. Un fichier .dat permet aussi de gérer l'archivage, ce qui est un problème intéressant, lorsqu'on fait une démo à mon humble avis. Le comportement typique, c'est (en mode développement) d'aller chercher les fichiers dans l'archive, et s'il n'y sont pas où s'il y a une version plus récement modifiée sur le disque il faut remplacer le fichier existant dans l'archive et réécrire le tout sur le disque. On peut aussi gérer un historique des versions de chaque asset (shaders, modèles 3d, musique, textures...) au besoin, comme ça si on regrette un changement, on peut revenir facilement à une version antérieure.

J'ai utilisé une interface comme ça dans la dernière version de mon moteur de démos, même si c'est un peu... porc, j'avoue. Je ne suis pas très satisfait et je pense que ça leake un peu de mémoire... Bref à réitérer donc. C'est basé plus ou moins sur le design template composite, ce qui permet de gérer des répertoires également dans le fichier .dat qui sont invisibles dans la distribution. Pas de parano, c'est juste pour trier les choses proprement là. :)

http://pastebin.com/j20F5eGe (http://pastebin.com/j20F5eGe)

Title: Re : Données dans exe
Post by: RaHoW on 19 May 2011 à 23:21:03
Mais pour les 64kb ce ne sont pas ses méthodes qui sont retenues. Pour la zik se sont les synths et pour les graphs c'est pratiquement que du procedural + shaders.

Bien sûr, mais que je sache, même si c'est "pas moderne" et que "ça plait pas au "tout-pouet" ", aucune loi à ma connaissance n'interdit de faire des 64k "à l'ancienne", avec un bon vieux XM et quelques gfx par ci par là ^^
Title: Re : Re : Données dans exe
Post by: LLB on 20 May 2011 à 00:24:38
Ça m’intéresse énormément, parce que même en faisant un incbin ou un tableau binaire, je ne vois pas trop comment "simuler" le fait de charger le fichier (autant je peux peut être modifié mon code, autant loader une track en miniFmod ou quoi de cette manière... je vois pas comment faire)...
Tout ce que tu récupères, c'est un pointeur sur les données. Il faut regarder dans miniFmod s'il y a une fonction prenant en entrée un pointeur de données, au lieu d'un nom de fichier. Je sais que c'est possible avec uFmod (je l'ai déjà fait).
Title: Re : Données dans exe
Post by: Okeanos on 20 May 2011 à 07:10:26
Bien sûr, mais que je sache, même si c'est "pas moderne" et que "ça plait pas au "tout-pouet" ", aucune loi à ma connaissance n'interdit de faire des 64k "à l'ancienne", avec un bon vieux XM et quelques gfx par ci par là ^^

Non, rien ne l'interdit au contraire...
Je dis juste que pour gagner de la place mieux vaux faire appel à ces méthodes car elles sont moins lourdes. Et le gain de place est essentiel quand tu fais une 4k ou une 64k.
Par exemple avec un XM, tu montes vite en kb (samples 8bits digitalisés) alors que le synth non. Les musiques faites avec V2 sont extrêmement "légères" et le son est similaire à un XM.
Idem pour les graphs, générer les textures bouffe moins de kb que de "packer" un BMP ou un JPG.