ORG &2000
NOLIST

; Turbo Cruncher decrunching routine * Elmsoft (c) 1992
; Reverse ingeenering (hum...) by T&J/GPA (c) 2003
; Merci le Hacker pour le source ASCII initial...


; La routine peut s'utiliser de deux facons.

; Standard, sans parametre. Ces derniers sont definis en dur.

; Personnalise. La variable flag_perso doit etre a 0 et IX doit pointer sur
; une table de mots organises comme suit :

      DEFW longueur    ; longueur des donnees compactees
      DEFW decompacte  ; adresse de debut du code a decompacter
      DEFW givenstart  ; adresse de debut du code compacte

; Les petits malins auront remarques que notre ami Elmsoft a prevu ce buffer 
; dans le corps de la routine...


2000  DI   
2001  LD   HL,&E9E1    ; = POP HL  JP (HL)
2004  LD   (&0026),HL
2007  CALL &0026       ; HL=adresse d'execution de la routine + &A
200A  JR   &2013

; Variables utilisees par la routine

200C  db flag_perso    ; flag permettant de savoir s'il faut utiliser ou pas
                       ; la variable givenstart

                       ; &00 = on considere l'adresse comme base du code
                       ; compacte
                       ; &01 = on calcule l'adresse de base du code compacte
                       ; a partir de l'adresse d'execution de la routine de
                       ; decompactage.

200D  DEFW longueur    ; longueur des donnees compactees
200F  DEFW decompacte  ; adresse de debut du code a decompacter
2011  DEFW givenstart  ; adresse de debut du code compacte (pas utilise si
                       ; flag_perso <> &0

; Initialisation des differents pointeurs necessaires

2013  INC  HL
2014  INC  HL          ; HL pointe sur le debut de la table des variables
                       ; (soit &200C dans notre cas).

2015  LD   A,(HL)      ; On utilise l'adresse de decompactage givenstart ?
2016  INC  HL
2017  OR   A
2018  JR   Z,&201D     ; non, donc 

201A  PUSH HL          ; HL=&200D 
201B  POP  IX          ; IX pointe sur le debut des variables 16 bits

201D  LD   (&0026),SP  ; on sauve SP temporairement, afin se s'en servir pour
                       ; recuperer les variables utiles a la routine...

2021  LD   SP,IX       ; SP pointe sur &200D
2023  POP  IX          ; IX = longueur code compacte
2025  POP  DE          ; DE = pointeur sur code compacte

2026  OR   A            
2027  JR   Z,&202F     ; Si A pas egal a 0, HL pointe sur le debut de la
                       ; zone contenant les donnees compactees a la suite de
2029  LD   BC,&0096    ; la routine
202C  ADD  HL,BC       ; soit &20A3
202D  JR   &2030

202F  POP  HL         ; sinon, on recupere HL

2030  EX   DE,HL      
2031  ADD  IX,DE      ; on additionne IX a HL.
2033  EX   DE,HL      ; on a dans IX le mot de fin du code compacte

2034  LD   SP,(&0026) ; on remet le pointeur de pile a sa valeur initiale

2038  LD   A,H
2039  DB   &DD:CP A,H ; opcode comparant poids fort de IX avec A

203B  JR    C,&2044   ; si CARRY IXH > H donc on continue

203D  JR   NZ,&20A1   ; si pas Zero, fin du decompactage car on depasse la zone du code
                      ; compactee.
203F  LD   A,L
2040  DB   &DD:CP A,L ; opcopde comparant poids faible de IX avec A

2042  JR   NC,&20A1   ; HL=IX, Fin du decompactage

2044  LD   A,(HL)     ; HL pointe sur donnees packees 
2045  RLCA            ; test bit 7 
2046  JR   C,&2074    ; Si Carry, pas une chaine a recopier. On effectue
                      ; une autre serie de tests.

2048  RLCA            ; Bit 7=0, test bit 6
2049  JR   C,&205E    ; routine de recopie d'une chaine de + de 3 caracteres.


; Routine de recopie de 3 octets a partir d'une chaine deja presente dans
; le code decompacte

; En entree, &00 + decalage negatif.
; Cette routine accomplie la meme tache que la suivante, mais est optimisee
; pour les chaines 'courtes' (codage sur un octet au lieu de trois).

; Recopie en DE la chaine pointee par HL

204B  PUSH HL         ; bit 7 et 6 a 0, chaine de trois octets a recuperer
204C  LD   B,&00      ; dans le code deja decompacte.
204E  LD   C,(HL)
204F  LD   H,D
2050  LD   L,E
2051  OR   A
2052  SBC  HL,BC
2054  LDI  
2056  LDI  
2058  LDI  
205A  POP  HL
205B  INC  HL
205C  JR   &2038

; Routine de recopie d'une chaine de caracteres presente dans le code
; decompacte.

; Entree, &40 + longueur chaine a recopier
; deux octets suivants : index relatif en negatif de la chaine a recopier a
; partir du code deja decompacte.

; Recopie en DE la chaine pointee en HL de longueur BC

205E  LD   A,(HL)
205F  AND  &3F
2061  INC  HL
2062  LD   C,(HL)
2063  INC  HL
2064  LD   B,(HL)
2065  INC  HL
2066  PUSH HL
2067  OR   A
2068  LD   H,D
2069  LD   L,E
206A  SBC  HL,BC
206C  LD   B,&00
206E  LD   C,A
206F  LDIR 
2071  POP  HL
2072  JR   &2038

; Deuxieme serie de tests

2074  RLCA 
2075  JR    C,&208B ; bit 6 on, simple recopie de chaine

2077  RLCA          ; test bit 5
2078  JR    C,&2096

; Routine de decompactage de suite d'octets de meme valeur.

; Valeur en entree=&80 + nb d'occurrences de la valeur
; Octet suivant dans le code compacte = valeur a recopier

; Recopie en DE le caractere pointe par HL  BC fois.

207A  LD   C,(HL) 
207B  RES  7,C
207D  LD   B,&00
207F  INC  HL
2080  LDI  
2082  PUSH HL
2083  LD   H,D
2084  LD   L,E
2085  DEC  HL
2086  LDIR 
2088  POP  HL
2089  JR   &2038

; Routine de recopie d'une suite d'octets du code compacte vers le code
; decompacte.

; Valeur en entree = &C0 + nb de caracteres a recopier
; nb octets suivants representant la chaine a recopier

; Copie en DE la chaine pointee par HL de longueur BC

208B  LD   A,(HL)
208C  AND  &3F
208E  LD   C,A
208F  LD   B,&00
2091  INC  HL
2092  LDIR 
2094  JR   &2038

; Routine de recopie d'une suite d'octets du code compacte vers le code
; decompacte.

; Valeur en entree = &E0 +  octet fort du nb de caracteres a recopier
; octets suivant octet faible du nb de caracteres a recopier
; nb octets suivants re

; Copie en DE la chaine pointee par HL de longueur BC

2096  LD   A,(HL)
2097  AND  &1F
2099  LD   B,A
209A  INC  HL
209B  LD   C,(HL)
209C  INC  HL
209D  LDIR 
209F  JR   &2038

20A1  EI   ; retour au programme ayant appele la routine
20A2  RET  

20A3  DB 0 ; Debut des donnees compactees
opier
; octets suivant octet faible du nb de caracteres a recopier
; nb octets suivants re

; Copie en DE la chaine pointee 