
PUCRUNCH, l'ultime compacteur ?
------------------------------

Cet archive contient plusieurs sources de routines a utiliser pour 
decompacter un fichier compacte avec PUCRUNCH. Il contient aussi
la version Windows de PUCRUNCH.

Comme d'habitude, pas d'accent dans cet article.

Version 1.0 * Tom et Jerry/GPA le 02/07/2007


C'est quoi PUCRUNCH ?
---------------------
PUCRUNCH est un compacteur cree par un programmeur sur Commodore C64,
Pasi Ojala, qui presente la particularite de fonctionner sur PC.
Le programme est capable de generer des executables pour tous les
Commodore 8bits, mais permet egalement de creer des fichiers de
donnees simples.
Beneficiant de la puissance de calcul apportee par une plateforme
materielle recente, PUCRUNCH compacte de facon quasiment instantanee
tout fichier de taille modeste et utilise des techniques de recherches
complexes pour produire un taux de compression excellent, meilleur que
tout ce qui existe a ce jour sur CPC.

Des programmeurs Z80 se sont penches sur ce produit et ont cree des
routines permettant de decompresser un fichier PUCRUNCHed. Le premier
source diffuse semble avoir ete fait pour la Nintendo Gameboy en ...
1999 (qui a dit que les consoles ne servent a rien :-) ).
D'autres routine sont depuis sorties, mais aucune a ce jour n'avait
ete adaptee pour le l'Amstrad CPC.
Cette injustice est desormais reparee !


Les sources :
-------------
Site officiel de PUCRUNCH :
http://www.cs.tut.fi/~albert/Dev/pucrunch/

Routine GB par Jeff Frohwein : 
http://www.cs.tut.fi/~albert/Dev/pucrunch/uncrunch-z80.asm

Routine Z80 par Jussi Pitknen :
http://bree.homeunix.net/~ccfg/pucrunch/

Routine Sega Master System par Maxim :
http://www.smspower.org/maxim/smssoftware/pucrunch.html


L'archive ci-joint contient des versions CPC de ces routines plus 
deux versions inedites. Tous les sources sont compilables avec
Maxam, l'ultime assembleur sur CPC :-).

GB.ASM		Port Gameboy

Z80.ASM		Port "Z80"

GB_CPC.ASM	Version optimisee du port Gameboy

BASIC.ASM	Source Maxam du port Gameboy optimise avec passage des
		    parametres via un CALL sous Basic

GB.ASM
Taille en octets : &1C0
Le premier source est present a titre "historique". C'est celui qui
est le plus commente (en anglais) et le plus lisible car il n'utilise 
pas d'astuce de programmation.

Z80.ASM
Taile en octets : &129
Le second source est une version tres particuliere, utilisant les registres
secondaires du Z80 pour eviter de couteuses operations de lecture/ecriture
de variables en memoire. C'est la routine la plus rapide a la decompression
et la plus courte.

J'ai du modifier un peu le source pour qu'il fonctionne sous BASIC
(sauvegarde des registres secondaires BC, DE et HL).

Autre particularite, le source ne stocke pas dans une table les 31
octets necessaires a la decompression. Il va les lire dans l'en-tete
du code compacte. Si cette zone est ecrasee lors du decompactage,
plantage assure !
Il est bien evidemment facile de rajouter une copie de cette table
dans la routine, mais du coup, sa taille augmente un peu.

GB-CPC.ASM
Taille en octets : &18D
Une version optimisee du source Gameboy. La routine est un peu plus courte,
et environ 10% plus rapide a la decompression. Elle est moins performante
que Z80.ASM, mais travaille sans probleme sous interruption.
		
BASIC.ASM
Taille en octets : &19C
Une version de GB-CPC.ASM permettant de passer sous Basic les parametres
necessaires au decompactage par un simple CALL.		


Quelques considerations techniques sur le decompactage
------------------------------------------------------
L'implantation en memoire du code compacte
******************************************
En fonction de la taille du programme original et du code compacte,
il existe deux options pour determiner ou stocker en memoire le
fichier compacte.

Sur de petits fichiers, on peut implanter le code compacte dans une
zone qui n'est pas utilisee par le programme d'origine.

Un exemple : 
On compacte un programme utilisant la memoire entre &1000 et &5000.
Le code compacte fait &3000 de longueur.
On pourra sans risque implanter le code compacte en &5000, car cette
zone ne sera jamais ecrite par la routine de decompactage et le code
compacte n'est pas assez long pour "endommager" les zones memoire 
reservees au systeme (grossierement, au dessus de &A67B pour un CPC6128).
On pourrait aussi par exemple implanter le code compacte en memoire
video (&C000).

Sur un programme plus gros, il n'y aura pas assez de memoire "libre"
pour utiliser cette technique. On utilise alors le principe de la "zone
tampon". Le programme compacte est implante dans la zone memoire du
programme normal, mais avec un decalage suffisant pour que la fin du
programme compacte ne soit pas ecrasee lors du decompactage.
Comment determiner la taille de cette zone tampon ? Eh bien, cela depend
de la memoire qui reste disponible et du programme compacte.
On peut considerer qu'une zone tampon de &0100 est dans la plupart des
cas suffisante.

Si on reprend notre exemple :

	Programme standard utilisant la memoire entre &1000 et &5000
	Code compacte de longueur &3000
	Zone "tampon" : entre &5000 et &5100
	Implantation du code compacte : &5100-&3000 = &2100

Si le decompactage plante, il faut augmenter la taille de la zone
tampon.
 

Pourquoi Utiliser PUCRUNCH plutot qu'un autre compacteur ?
**********************************************************
La performance : PUCRUNCH est selon mes tests de 10 a 20% plus
performant que CPCT 3.0 (desole Yves !), la reference sur
CPC.

La vitesse : le compactage d'un programme est tres rapide. Plus
besoin d'attendre une demi-heure pour compacter un jeu !

La souplesse : PUCRUNCH etant un programme PC, la taille du
programme a compacter n'a pas d'importance. On peut ainsi
compacter de tres gros programmes, que seuls quelques rares
compacteurs comme le Crown Cruncher peuvent traiter.


PUCRUNCH a t'il des defauts ?
*****************************
Il faut disposer d'un PC. Je suppose que la plupart des utilisateurs
de CPC en sont equipes...

Par rapport a certains compacteurs qui s'occupent de tout, il est
necessaires d'avoir un minimum de bases sur l'organisation de la
memoire du CPC pour bien s'en servir. 

Le decompactage est plus lent que la majorite des autres crunchers
sur CPC. Cela reste neanmoins tout a fait correct au regard de la
taille des fichiers compactes.

Il n'y a pas de front-end, de programme qui vous prend en charge,
et vous evite de penibles calculs :-). D'un autre cote, l'usage
d'un source garantit une totale adaptabilite a vos besoin.



Exemple de compactage d'un ecran de presentation 17k
----------------------------------------------------

Dans l'archive DSK, vous trouverez le fichier BUGGY.SCR (transfert
de la page ecran C64 d'un jeu connu, Buggy Boy), qui nous servira
pour ce petit didacticiel.

1ere etape : transferer le fichier sur votre PC.
************
On peut par exemple utiliser ManageDsk de Demoniak. Seule regle 
IMPERATIVE, le fichier doit etre exporte SANS EN-TETE.
Si vous avez correctement fait le transfert, le fichier sur PC doit
avoir une taille de 16384 octets (soit &4000).

2eme etape : le compactage.
************
Copier le fichier BUGGY.SCR dans le meme repertoire que PCRUNCH.EXE.
Ouvrir une fenetre de commande en mode texte.
Taper la commande : PCRUNCH.EXE -C0 -D BUGGY.SCR BUGGY.CRU
Si tout se passe bien, vous devez voir dans le repertoire de travail
un nouveau fichier BUGGY.CRU, de 4500 octets (soit 1194 !).

3eme etape : le transfert vers le CPC.
************
Vous reprenez votre outil prefere, et vous importez sur une disquette
CPC le fichier BUGGY.CRU en mode BINAIRE. Le fichier n'a aucune 
adresse d'implantation ni d'execution par defaut.

4eme etape : Determiner les adresses d'implantation en memoire du
fichier compacte et du decompacteur.
************
Une page ecran etant implante en memoire video (&C000-&FFFF), nous avons
a notre disposition toute la ram "systeme" (&0040-&A67B pour un CPC 6128).
Le fichier compacte peut donc etre charge ou bon vous semble dans cette
zone.
Dans notre exemple, nous allons charger l'ecran en &4000.
La routine de decompactage utilisee sera celle utilisable directement en
Basic. Par defaut, elle est implantee en &A000.

5eme etape : Compiler le decompacteur.
************
Lancer Maxam. Charger avec la commande L (Load) le source BASIC.ASM.
Passer en mode edition avec la commande T (Text).
Compiler le source avec la commande A (Assemble).
>> Le programme BASIC.BIN est cree sur la disquette.

6eme etape : Creer un chargeur Basic pour l'image.
************
Le programme devra charger en memoire l'image compactee, la routine de
decompactage, puis lancer le decompactage.
En pratique, cela nous donne :

10 OPENOUT"D":MEMORY &3FFF
20 LOAD "BUGGY.CRU",&4000
30 LOAD "BASIC.BIN",&A000
40 CALL &A000,&4000,&C000

La ligne 40 contient l'appel a la routine. On lui transmet deux
informations :
- L'adresse de depart de l'ecran compacte
- L'adresse de depart ou decompacter l'image (soit le debut de la
  memoire video)

Simple, non ?



Exemple de compactage de programme, Boulder Dash
------------------------------------------------

Basiquement, la methode est identique au compactage d'une page ecran.
Il faudra simplement personnaliser la routine de decompactage et bien
veiller a ce que le code compacte ne soit pas corrompu lors de la
decompression. 
Dans cet exemple, nous travaillerons avec le jeu Boulder Dash. La
version la plus courante de ce programme se presente sous la forme
d'un fichier BOULDER.BIN de 29ko dont les caracteristiques sont :

	Adresse d'implantation : &0200
	Longueur : &7025
	Adresse d'execution : &1F52		

1ere etape : transferer le fichier sur votre PC.
************
On peut par exemple utiliser ManageDsk de Demoniak. Seule regle 
IMPERATIVE, le fichier doit etre exporte SANS EN-TETE.
Si vous avez correctement fait le transfert, le fichier sur PC doit avoir
une taille de 28709 octets (soit &7025)

2eme etape : le compactage.
************
Copier le fichier BOULDER.BIN dans le meme repertoire que PCRUNCH.EXE
Ouvrir une fenetre de commande en mode texte.
Taper la commande PCRUNCH.EXE -C0 -D BOULDER.BIN BOULDER.CRU
Si tout se passe bien, vous devez voir dans le repertoire de travail un
nouveau fichier BOULDER.CRU, de taille 11532 (soit &2D0C !).

3eme etape : le transfert vers le CPC.
************
Vous reprenez votre outil prefere, et vous importez sur une disquette
CPC le fichier BOULDER.CRU en mode BINAIRE. Le fichier n'a aucune 
adresse d'implantation ni d'execution par defaut.

4eme etape : Determiner les adresses d'implantation en memoire du
fichier compacte et du decompacteur.
************
Soyez attentif, cela devient un peu plus technique (mais pas complexe
pour autant).
Comme nous l'avons vu dans le paragraphe precedent, pour etre sur que
le decompactage ne se traduise pas par un plantage, il est necessaire
de faire en sorte que les dernieres donnees compactees chargees en
memoire ne soient pas ecrasees par le code decompacte.

Pour BOULDER DASH, la fin du programme "normal" se trouve en
(&200 + &7025) -1, soit &7224. Il nous reste donc beaucoup de memoire pour
loger la routine de decompactage et la zone "tampon".

Dans notre exemple, nous allons implanter la routine de decompactage en
&7800. Le fichier compacte sera charge juste en dessous, soit :

	&7800 - longueur du fichier compacte
	&7800 - &2D0C = &4AF4

5eme etape : compiler une version specifique du decompacteur.
************
BOULDER DASH etant implante assez bas en memoire, il n'est pas tres
pratique d'utiliser un chargeur Basic. L'appel a la routine de 
decompactage devra donc etre immediatement enchaine par l'execution
du jeu, sans revenir au Basic.
Pour ce faire, il faut juste rajouter au debut de la routine que vous
avez choisie (GB.ASM, Z80.ASM ou GB_CPC.ASM)

	LD HL,&4AF4
	LD DE,&0200
	CALL routine
	JP &1F52

Compiler ensuite le source. Vous devez obtenir un fichier GB.BIN, GB-CPC.BIN
ou Z80.BIN. Si les fichiers n'ont pas ete modifies, ils doivent avoir la
taille suivante :

		GB.BIN
		Z80.BIN
		GB-CPC.BIN

A ces longueur, il faudra rajouter celle du code que nous avons rajoute, soit
12 octets.

6eme etape : On fusionne tout ce bazar !
************
Nous devons d'abord determiner la longueur finale du programme avec le 
decompacteur integre.
Le calcul est donc le suivant :
  
  longueur du fichier compacte
+ longueur de la routine de decompactage

Pour Boulder Dash, on obtient (exemple avec source GB-CPC) :

	&2D0C + (&18D + 12) = &2EA5

Maintenant, un simple petit programme Basic nous permettra de creer enfin
un fichier unique.

10 OPENOUT"D":MEMORY &4AF9
20 LOAD "BOULDER.CRU",&4AFA
30 LOAD "GB_CPC.BIN",&8000
40 SAVE "BOULDER.BIN",B,&4AF9,&2EA5,&8000

Au final, on se retrouve avec un executable de 12Ko au lieu de 29 !