[ZX81:TUTO] L'affichage... compression & co.

Cette catégorie traite de développements récents destinés à nos vieilles machines, applications, jeux ou démos... Amis programmeurs, c'est ici que vous pourrez enfin devenir célèbres!

Modérateurs : Papy.G, fneck, Carl

Xavier

[ZX81:TUTO] L'affichage... compression & co.

Message par Xavier »

[ZX81:TUTO] L'affichage... compression & co.

Bonjour à tous,
J'aimerai partager avec vous une réflexion sur l'affichage écran du ZX81.

Présentation du ZX81:
Le Zx81 est un ordinateur muni d'un Zilog (clone du 8080) avec 1k octets en version de base.
La rom de 8K possède un basic qui gère une taille mémoire de 16k maximum (limitation constructeur). Il est à noter que Sinclair n'a JAMAIS fabriqué ou fait fabriquer d'extension mémoire supérieur à 16k, de peur que les utilisateurs ne lui reproche cette limitation due au test mémoire de la ROM !

L'affichage est simple, et ne possède pas d'UDG (redéfinition graphique), mais une police de caractère de 63 symboles (alpha et graphique).

Image

Cette police de caractère peut être affichée en vidéo inversé en activant le bit 7 à l'affichage.
Le Bit 6 des caractères n'est utilisé qu'en basic pour afficher les commandes et les fonctions Basic.

Le Zx81 a la particularité d'avoir sa mémoire vidéo juste après le programme Basic, ce qui rend son emplacement "flottant", imposé par la taille du programme basic!
Mais une valeur D_File système permet de connaître la valeur de l'offset du premier caractère de la mémoire vidéo.
Pour l'affichage, il suffit de poker directement dans cette mémoire, en évitant de supprimer un caractère de retour à la ligne... fatale au basic, car cela désorganise l'affichage... et fini par afficher le VARS (mémoire des variable, ainsi que le reste de la mémoire, jusqu'en haut des 16k ou se trouve les piles du CPU)...Donc, plantage!


Structure vidéo (16K):
32 caractères + $76 (retour à la ligne)
32 caractères + $76 (retour à la ligne)...
... 24 fois, puis l'on trouve le VARS, où sont stockés les variables.

En version 1k, la rom "compresse" l'écran en éliminant le espaces jusqu'en fin de

ligne:
BONJOUR+$76
$76
$76
... 24 fois
Ce qui permet de ne pas encombrer la mémoire!

Avec une extension mémoire, la taille de la mémoire écran est fixe, avec ses 32 caractère x24 lignes+24 retour à la ligne = 792 octets.

Si l'on veut sauvegarder un dessin, il faut donc 792 octets... ou 768 octets si l'on ne sauvegarde pas les retours à la ligne.
Donc, 16k (16384 octets) peuvent contenir un certain nombre d'écrans... mais combien?

Soit un RAM de 16384 octets:
- 130 octets système.
- 792 octets mémoire vidéo.
- 255 octets pour la pile.
- 2 octets pour les variable (on travail en langage machine)
- 30 octets de Basic.
- 30 octets de langage machine.
= 15145 octets pour les images.
\768 = 19 images plein écran.

L'objet de cette étude est de compresser les images pour que le stockage soit moins gourmand!


Compression par élimination de redondances:
Donc, j'ai encodé les images comme suit:
Soit "XXXXXXAAAAABA..." à l'écran sur la même ligne.
Donc, j'ai 6*"X";5*"A";1*"B";1*"A" = 13 octets.

Vu que le bit6 n'est pas utilisé pour l'affichage, je l'utilise pour "Taguer" le caractère pour indiquer qu'il est répéter * fois.
X!6 A!5 B A (pas de tag pour les lettres non répétées)
Vu que le codage ce fait sur deux octets un DATA et un Multiplicateur, le second est limité à $FF, donc 255 fois.
Un écran blanc (768*" " ou 768*CHR$(0)) est encodé comme suit:
(0 or BIT6) x 255;(0 or BIT6) x 255;(0 or BIT6) x 255
Donc:$40$FF$40$FF$40$FF (6 octets au lieu de 768 octets)
C'est un exemple, car stocker un écran vide est inutile.

Image exemple:
Image

Non codée:
Image

Codée:
Image

Donc, cet encodage évitera les répétitions inutiles.
Tout va dépendre de la complexité de l'image, car si aucune redondance n'est possible, la taille codée et décodée sera identique.
Il est à noter que ce codage ne fonctionne pas avec les données binaires, mais seulement avec les textes, et les images.

Routines ASM et fichier 'P'(compression et décompression sans buffer):
http://zx81.ordi5.free.fr/xavsnap/xpict ... i_zx81.zip

Compression LZ:
On pourrai s'arrêter là, mais j'ai trouvé une routine Z80 pour décoder les fichiers LZ sur Amstrad CPC et Game Boy... Cette routine n'est pas trop lourde et pèse moins de 300 octets... mais permet de réduire les images.
Cette méthode est basée sur le logiciel "PUcrunch" sous PC DOS, et en important les fichiers générés, il est possible de les stocker en mémoire pour une décompression ultérieur.

Pour 16K d'images, je récupère 3K d'espace libre en comptant la routine LZ. (ce qui est non négligeable!)

Routines ASM et fichier 'P':
http://zx81.ordi5.free.fr/xavsnap/xpict ... Z_ZX81.zip

Seul problème, nous avons besoin d'un buffer de décompression pour pouvoir décoder les datas avec le système précédent... donc au pire, 768 octets en moins.
Il serait donc intéressant de décompresser directement en mémoire vidéo, mais cela implique une taille des fichiers compactés "DATAs" plus important qu'avec les deux méthodes de compression.

Routines ASM d'une démo avec pas moins de 30 images en "full screen" et fichier 'P' exécutable sur émulateur:
(seront ajoutées par la suite)

L'ensemble du travail n'est pas encore effectué, mais cela plante le décor pour la suite... :arrow:
__sam__
Messages : 7964
Inscription : 18 sept. 2010 12:08
Localisation : Brest et parfois les Flandres

Re: [ZX81:TUTO] L'affichage... compression & co.

Message par __sam__ »

Regarde du coté de la compression EXOMIZER2. Elle utilise seulement 156 octets de buffer et occupe (sur 6809) environ 181 octets pour le decompresseur (mais le 6809 produit du code hyper compact).

==> http://hem.bredband.net/magli143/exo/

Discussion pour le 6809 + code: http://www.logicielsmoto.com/phpBB/view ... 3201#p3201
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Xavier

Re: [ZX81:TUTO] L'affichage... compression & co.

Message par Xavier »

Oui, j'ai...
Je passe au test dès la fin de la démo!
Mais, il semble un peu plus lourd...

Code : Tout sélectionner

; ******************************************************
; **       Librería de rutinas para Amstrad CPC       **
; **	   Raúl Simarro, 	  Artaburu 2007       **
; ******************************************************


XLIB cpc_UnExo


.cpc_UnExo

;Exomizer 2 Z80 decoder
; by Metalbrain
;
; compression algorithm by Magnus Lind

;input  	hl=compressed data start
;		de=uncompressed destination start
;
;		you may change exo_mapbasebits to point to any free buffer

pop af
pop de
pop hl
push af

di
call deexo
ei

ret

.deexo

		ld	ixh,128
		ld	b,52
		ld	iy,exo_mapbasebits

		push	de

.exo_initbits

	ld	a,b
		sub	4
		and	15
		jr	nz,exo_node1

		ld	de,1		;DE=b2
.exo_node1
	ld	c,16

.exo_get4bits
	call	exo_getbit
		rl	c
		jr	nc,exo_get4bits
		ld	(iy+0),c	;bits(i)=b1

		push	hl
		inc	c
		ld	hl,0
		scf
.exo_setbit
	adc	hl,hl
		dec	c
		jr	nz,exo_setbit
		ld	(iy+52),e
		ld	(iy+104),d	;base(i)=b2
		add	hl,de
		ex	de,hl
		inc	iy
		pop	hl
		djnz	exo_initbits
		inc	c
.exo_literalseq
	pop	de
.exo_literalcopy
	ldir			;copy literal(s)

.exo_mainloop
	ld	c,1
		call	exo_getbit	;literal?
		jr	c,exo_literalcopy
		ld	c,255
.exo_getindex
	inc	c
		call	exo_getbit
		jr	nc,exo_getindex
		ld	a,c		;C=index
		cp	16
		ret	z
		jr	c,exo_continue
		push	de
		ld	d,16
		call	exo_getbits
		jr	exo_literalseq
.exo_continue
	push	de
		call	exo_getpair
		push	bc
		pop	af
		ex	af,af'		;lenght in AF'
		ld	de,512+48	;1?
		dec	bc
		ld	a,b
		or	c
		jr	z,exo_goforit
		ld	de,1024+32
		dec	bc		;2?
		ld	a,b
		or	c
		jr	z,exo_goforit
		ld	e,16
.exo_goforit
	call	exo_getbits
		ld	a,e
		add	a,c
		ld	c,a
		call	exo_getpair	;bc=offset
		pop	de		;de=destination
		push	hl		
		ld	h,d
		ld	l,e
		sbc	hl,bc		;hl=origin
		ex	af,af'
		push	af
		pop	bc		;bc=lenght
		ldir
		pop	hl		;Keep HL, DE is updated
		jr	exo_mainloop	;Next!

.exo_getpair
	ld	iy,exo_mapbasebits
		ld	b,0
		add	iy,bc
		ld	d,(iy+0)
		call	exo_getbits
		ld	a,c
		add	a,(iy+52)
		ld	c,a
		ld	a,b
		adc	a,(iy+104)
		ld	b,a
		ret

.exo_getbits
	ld	bc,0		;get D bits in BC
.exo_gettingbits
	dec	d
		ret	m
		call	exo_getbit
		rl	c
		rl	b
		jr	exo_gettingbits

.exo_getbit
	ld	a,ixh		;get one bit
		add	a,a
		ld	ixh,a
		ret	nz
		ld	a,(hl)
		inc	hl
		rla
		ld	ixh,a
		ret

.exo_mapbasebits

defs	156	;tables for bits, baseL, baseH
Xavier

Re: [ZX81:TUTO] L'affichage... compression & co.

Message par Xavier »

Entre nous, le plus long c'est de dessiner les 30 images pour la démo !!!
Même avec le "Easy-draw" du Xur, il faut les retravailler sur deux niveaux de compression...

côté émulateur:
"Heighty-one"=Rigoureux.
"Xur"=Ludique pour la programmation et la création.
"Sz81"=Pour le son et la jouabilité au joystick.

"Eighty-one" (win32): ftp://ftp.worldofspectrum.org/pub/sincl ... One1.0.zip
le "Xur"(win32): http://zx81.vb81.free.fr
"Sz81"(win32/linux): http://sz81.sourceforge.net/
Dernière modification par Xavier le 05 mars 2020 01:57, modifié 1 fois.
Avatar de l’utilisateur
6502man
Messages : 12312
Inscription : 12 avr. 2007 22:46
Localisation : VAR
Contact :

Re: [ZX81:TUTO] L'affichage... compression & co.

Message par 6502man »

J'ai porté exomizer sur hector HRX et il est très petit et rapide à la décompression.

Je pense que sur Zx-81 ca doit être faisable, mais pas sur que cela permette de gagner énormément sur 768 octets :roll:
Phil.

www.6502man.com

To bit or not to bit.
1 or 0.
Xavier

Re: [ZX81:TUTO] L'affichage... compression & co.

Message par Xavier »

Au pire, on gagne un tiers de l'image, mais la taille des fichiers imposent une compression multiple des images, donc la répétition des headers... à moins de décompresser un binaire unique à partir d'un point précis! idée à approfondir, mais la décompression sera plus lente car il faudra tester l'ensemble du fichier pour en récupérer un petite partie! (texte de description, décore...)
Répondre