[SHARP MZ-700] BRICK BUSTER

Cette catégorie traite de développements récents pour 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

hlide
Messages : 1706
Enregistré le : 29 nov. 2017 10:23

Re: [SHARP MZ-700] BRICK BUSTER

Message par hlide » 11 mai 2020 15:23

Aujourd'hui je vais parler de la raquette.

La raquette c'est 5 ou 7 caractères contigus à afficher. Il en sort une propriété intéressante : je n'ai pas besoin de coordonnées X et Y. En effet, la position m'est donnée directement par son adresse en VRAM (qui commence en $D000) et comme la ligne 23 (40 caractères en largeur) est comprise ente $D398 et $D3C0, je peux me limiter à considérer l'octet de poids faible de cette adresse pour confiner la raquette dans une intervalle légèrement plus petite en magnitude que ]$98, $B6[ (la magnitude est de 30 et non 40 caractères lors du jeu).

Pour bouger il me suffit d'incrémenter ou de décrémenter le poids faible de son adresse en restant dans l'intervalle adaptée à la dimension de la raquette. Pour gérer le rebond de la balle, je teste d'abord si la position Y de la balle est 23 et si c'est le cas, je vérifie que le poids faible de l'adresse calculée de la balle est dans l'intervalle des poids faibles min et max de l'adresse de la raquette.

Ça fonctionne bien mais il y a un hic : il y a 50 images par seconde, donc 50 déplacements de la raquette par seconde ! j'ai beau appuyé et relâché le plus court possible, ma raquette bouge pas moins de deux caractères.

Pour m'assurer que la boucle de jeu reste simple, j'ai décidé de rajouter une "vitesse" et une "accélération" à la raquette. A 50 FPS, n'espérez pas quelque chose de fluide à cause de la représentation en caractère : il s'agit de permettre faire le mouvement de 1 caractère immédiat avec une accélération exponentielle pour embrayer sur un déplacement rapide en touche continue.

Comment ? je procède comme si j'avais un nombre fixe 16.8 au lieu de 16.0 initialement. La partie fractionnaire ne sert pas de position mais de valeur initiale de "vitesse". Il sera toujours 128 sans déplacement, de 0 à l'amorce de déplacement à gauche et de 255 à droite. L'accélération est également initialisée au changement de direction à une valeur arbitraire (actuellement 00011111b - plus elle est petite, plus la raquette mettra du temps à rentrer en vitesse optimale après le déplacement initial).

Voici comment j'incrémente/décrémente la position de la raquette avec une pseudo vitesse et une pseudo accélération :

Code : Tout sélectionner

RACKET_ACCEL	EQU 00011111b ; valeur la plus grande qui me permet un déplacement de 1 caractère sans artefacts par la suite 
...
@1:		JR		Z,@0f ; direction positive, on saute car c'est déplacement à gauche là
		LD		A,(DE) ; DE contient l'adresse de l'octet "vitesse" de la raquette
move_racket_laccel: ; accélération à gauche
		SUB		RACKET_ACCEL ; ici, on devrait avoir un nombre de type -((2^n)-1)
		DEC		A ; mais on veut faire -(2^n)  !
		LD		(DE),A ; mise à jour de la vitesse
		LD		BC,0 ; joie du Z80 avec ses limitations en 16-bit
		SBC		HL,BC ; met à jour l'addrese de position de la raquette
		LD		A,L ; mais à ce niveau seul le poids faible compte
move_racket_posmin:
		CP		RACKET_POSITION_MIN+3 ; "leftmost" position?
		JR		Z,@2b
		LD		(racket_new_position),HL	; Met à jour la position à raquette
		LD		HL,move_racket_laccel+1 ; accélère "exponentiellement" la vitesse à gauche
		SLL		(HL) ; multiplie par 2 et rajoute 1 en bit 0 et cape la valeur à 255 ! 
		RET ; c'est fini
@0:		LD		A,(DE)
move_racket_raccel: ; même chose mais à droite !
		ADD		A,RACKET_ACCEL ; ici, on devrait avoir un nombre de type +(2^n)-1
		INC		A ; mais on veut faire +(2^n)  !
		LD		(DE),A
		LD		BC,0
		ADC		HL,BC
		LD		A,L
move_racket_posmax:
		CP		RACKET_POSITION_MAX-2		; "rightmost" position?
		JR		Z,@2b
		LD		(racket_new_position),HL
		LD		HL,move_racket_raccel+1 ; accélère "exponentiellement" la vitesse à droite
		SLL		(HL) ; multiplie par 2 et rajoute 1 en bit 0 et cape la valeur à 255 !
		RET
En faisant varier RACKET_ACCEL, j'obtiens un résultat plus ou moins bien. L'accélération exponentielle est bien trop rapide pour l'apercevoir et espérer une accélération harmonieuse (déplacement par caractère). Le but est essentiellement de conserver la vitesse tout en permettant de se déplacer par pas de 1 quand c'est souhaitable.
Modifié en dernier par hlide le 11 mai 2020 23:19, modifié 1 fois.

hlide
Messages : 1706
Enregistré le : 29 nov. 2017 10:23

Re: [SHARP MZ-700] BRICK BUSTER

Message par hlide » 11 mai 2020 23:09

Mise à jour du poste initial avec des images GIF en lieu et place des images statiques pour mieux rendre compte de la cinématique actuelle (en fin sur du 25 FPS au lieu de 50 FPS, c'est moins évident).

hlide
Messages : 1706
Enregistré le : 29 nov. 2017 10:23

Re: [SHARP MZ-700] BRICK BUSTER

Message par hlide » 23 mai 2020 00:10

Dernière réalisation en date en vidéo avec plus d'effet visuel :

ricco59
Messages : 68
Enregistré le : 23 mai 2007 22:13
Localisation : Près d'Arras

Re: [SHARP MZ-700] BRICK BUSTER

Message par ricco59 » 24 mai 2020 11:40

EXcellent boulot et belle maitrise du mode caractère ainsi que de la machine :)

Je vais suivre les evolutions

Bon dimanche

Eric
Dev en cours
* StepFive > Atari Falcon030 (en pause)
* W.I.I (Where Is It ?) > Colecovision (en cours)

hlide
Messages : 1706
Enregistré le : 29 nov. 2017 10:23

Re: [SHARP MZ-700] BRICK BUSTER

Message par hlide » 24 mai 2020 22:01

Merci Eric !

En pensant à cette histoire de compteur de lignes dans le jeu VG5000 Lode Runner, je me suis dit que je devais regarder du côté de mon jeu.

En fait, j'avais entièrement désactivé les interruptions par un DI en début du programme, car je n'en avais pas besoin et j'avais rapidement créé ma routine de scrutation des touches qui permet de connaître l'état pressé d'un touche indépendamment d'une autre. Du coup je n'utilisais plus la ROM monitor qui devient inutile. Je peux passer la zone de la ROM en DRAM pour installer directement mon RET à l'adresse $0038.

Mais je me suis dit que ce serait bien de "compter" les lignes en utilisant cette interruption qui servait à compter le passage en matin/après-midi avec correction de la date en seconde par le monitor. Là, je n'ai aucun intérêt avec cette fonctionnalité. Deux compteurs du PIT8253 entrent en jeu :
mz8253bl.gif
mz8253bl.gif (3.78 Kio) Vu 724 fois
On voit que le compteur 1 sert à compter des secondes et que le compteur 2 déclenche au bout d'une demi-journée une interruption qui va servir à modifier l'indicateur AM/PM du monitor et à réajuster le compteur 1 pour corriger une dérive des secondes.

Je me suis dit que je pourrais utiliser cette paire pour recréer le compte de /VSYNC indirectement. Normalement le PAL a 312 lignes. Pour ce faire, je fais en sorte que le compteur 1 (toujours mode 2) compte non plus les secondes mais les BLNK et je mets le compteur 2 à 312 BLNK avant qu'il ne déclenche l'interruption.

Code : Tout sélectionner

CNT1					EQU	1
CNT2					EQU 312
_main:	DI
		LD		SP,$C000
		OUT		($E0),A					; set area $0000-$0FFF as DRAM
		LD		A,$C9					; put RET at $0039 (RST $38)
		LD		($0038),A

		LD		HL,$E007				; $E007 - counter control
		LD		(HL),$74				; counter #1 - MODE 2 - set LSB counter then MSB counter
		LD		(HL),$B0				; counter #2 - MODE 0 - set LSB counter then MSB counter
		LD		L,$05					; $E005 - counter #1
		LD		(HL),(CNT1>>0)&255
		LD		(HL),(CNT1>>8)&255
		INC		L						; $E006 - counter #2
		LD		(HL),(CNT2>>0)&255
		LD		(HL),(CNT2>>8)&255
Maintenant ma routine d'attente de la vsync va faire trois choses : faire un HALT puis attendre la /VSYNC puis remettre les compteurs (réajustement par rapport au vsync) :

Code : Tout sélectionner

@4:		LD		HL,$E002
		EI
		HALT
		DI
		LD		A,$7F
@0:		CP		(HL)
		JP		NC,@0b
@0:		CP		(HL)
		JP		C,@0b
		LD		L,$05
		LD		(HL),(CNT1>>0)&255
		LD		(HL),(CNT1>>8)&255
		INC		L
		LD		(HL),(CNT2>>0)&255
		LD		(HL),(CNT2>>8)&255
		RET
Je note qu'avec un CNT2 supérieur à 312, on perd une frame sur deux donc je suis en bonne voie pour avoir un détecteur de dépassement pour le débogage.
Modifié en dernier par hlide le 24 mai 2020 23:12, modifié 3 fois.

hlide
Messages : 1706
Enregistré le : 29 nov. 2017 10:23

Re: [SHARP MZ-700] BRICK BUSTER

Message par hlide » 24 mai 2020 23:06

En regardant de plus près la routine de détection de /VBLNK, j'ai tiqué un peu pour deux raisons. La première : le signal dure un peu plus que 7 ms, ce qui veut dire que cette routine (piquée d'une démo) va attendre que le signal passe de 1 à 0 puis de 0 à 1. Ça m'ennuie car j'aimerais récupérer ces 7 ms. Deuxième raison : pour détecter le bit 7 à 1, elle fait "si $7F >= (hl) boucler" alors que $80 >= (hl) me semblerait plus approprié ici.
J'ai donc corriger ces deux aspects et je note un effet : si le CNT2 est légèrement supérieur à 312, j'ai toujours un semblant de 50 fps au lieu de 25 fps sans la "correction" de la routine mais on peut voir un tearing lent sur la raquette qui alterne ses couleurs entre chaque frame. A 312, elle est impeccable. Je pense que je vais garder cette "correction" couplée au compteur à 312 pour gagner 7 ms à l'intention du CPU.

Avatar du membre
6502man
Messages : 10098
Enregistré le : 12 avr. 2007 22:46
Localisation : VAR
Contact :

Re: [SHARP MZ-700] BRICK BUSTER

Message par 6502man » 28 mai 2020 21:58

Super ce développement sur MZ-700 :D

C'est déjà pas mal du tout pour la machine :wink:
Phil.

www.6502man.com

To bit or not to bit.
1 or 0.

hlide
Messages : 1706
Enregistré le : 29 nov. 2017 10:23

Re: [SHARP MZ-700] BRICK BUSTER

Message par hlide » 28 mai 2020 22:26

Merci 6502man.

Petit bonus - rien à avoir avec le jeu : on connaissait les dessins de PETscii, voici deux variations version SHARP que j'ai faites pour illustrer une cassette (qui sait pour un loader).
100906633_10223248310864386_3037524867437035520_n.jpg
100906633_10223248310864386_3037524867437035520_n.jpg (16.96 Kio) Vu 679 fois
99425364_10223247493083942_4846114606277459968_n.jpg
99425364_10223247493083942_4846114606277459968_n.jpg (16.97 Kio) Vu 679 fois

Avatar du membre
6502man
Messages : 10098
Enregistré le : 12 avr. 2007 22:46
Localisation : VAR
Contact :

Re: [SHARP MZ-700] BRICK BUSTER

Message par 6502man » 28 mai 2020 22:47

:D

Sympa les K7 en ASCII ART
Phil.

www.6502man.com

To bit or not to bit.
1 or 0.

hlide
Messages : 1706
Enregistré le : 29 nov. 2017 10:23

Re: [SHARP MZ-700] BRICK BUSTER

Message par hlide » 30 mai 2020 11:40

Retour sur le jeu.

Si vous avez vu la dernière vidéo, nous noterez qu'il n'y a pas de scintillement de caractères en dehors de l'effet voulu. C'est dû principalement à deux choses :
- tout le dessin est synchronisé sur une frame et ne déborde pas sur la suivante.
- le dessin est fait dans un ordre précis et le background sert à effacer.

1) Comment j'efface la balle ? la VRAM des caractères se trouve à partir de $D000 et de $D800 pour les couleurs. Initialement, j’effaçais avec le caractère $00 (espace) et la vouleur $00 (noir sur noir). Mais avec cette histoire de grille en fond, il me fallait faire autrement. J'ai donc décidé d'allouer la DRAM $C000 pour les caractères du fond et $C800 pour leur couleur. L'idée est que je n'ai besoin que de l'ancienne position VRAM pour obtenir l'adresse source via a "RES 4,H" (si VRAM est dans HL) et de revenir à la VRAM avec "SET 4,H". Ça fonctionne bien mais vu que que je dois passer par SP et POP pour la source, toujours SP et PUSH pour la destination pour mettre un maximum de caractère et de couleur dans la limite des 91 cycles par ligne de pixel, ça engendre un peu plus d'instructions. Aussi je me demandais si je ne pouvais pas utiliser avantageusement la DRAM qui se trouve à la même adresse que la VRAM ?
poweron.gif
poweron.gif (4.83 Kio) Vu 639 fois
Comment ? en faisant simplement "OUT ($E1),A" (il ignore la valeur de A) pour passer en DRAM comme source et accéder au fond entreposé à cet endroit. Puis un "OUT ($E3),A" pour retourner en VRAM comme destination et écrire le fond lu précédemment. Certes, c'est 11 cycles mais plus besoin de changer le SP pour passer en destination. Enfin presque, car je dois gérer les caractères Et les couleurs donc c'est un peu moins vrai.

2) Pour pouvoir dessiner tous les éléments variables autres que la balle et la raquette, j'utilise une curieuse façon de stocker dynamiquement mes routines de dessin dans la pile. La fonction qui sert à remplir la pile a un prologue et un épilogue qui ressemble à ça :

Code : Tout sélectionner

; -----------------------------------------------------------------------------
; Fill draw items queue
; ---------------------
fill_draw_items_queue:
		POP		HL
		LD		(fill_draw_items_queue_ret+1),HL

		LD		HL,draw_items_ret ; last exit routine of draw_items
		PUSH	HL
...
fill_draw_items_queue_ret:
		JP		$0000 ; saved RET address 
La raison est que je veux que cette fonction remplisse la pile avec des adresses de fonction de dessin optionnellement suivi d'arguments pour la fonction (généralement un adresse en VRAM où dessiner et l'adresse source du motif caractère/couleur qui peut varier entre chaque appel).

Plus tard, une autre fonction (draw_items) est appelée pour le dessin :

Code : Tout sélectionner

		; /VBLANK synchonized
		CALL	wait_vblank

		; draw objects		
		CALL	draw_ball			; draw ball
		CALL	draw_racket			; draw racket
		CALL	draw_items			; draw bricks
cette fonction dessine dans l'ordre inverse du remplissage de la pile en dépilant les routines de dessin de la pile :

Code : Tout sélectionner

; -----------------------------------------------------------------------------
; Draw items
; -----------
draw_items:
		POP		HL
		LD		(draw_items_ret+1),HL
		RET ; dépile les routines de dessin en les exécutant
draw_items_ret:
		JP		$0000
Je peux donc dessiner en fonction de l'état de chaque entité (briques, éclair, score, etc.) ou les effacer quand c'est nécessaire.

Dans le cas de la vidéo, les briques et le score sont dessinés systématiquement pour avoir une idée des ressources disponibles pour dessiner tout sous 50 FPS.

Il reste encore du travail :
- faire que les briques deviennent des vrais entités avec un état gérant leur animation, leur temps de vie, la colision avec la balle, etc. je reste encore indécis sur les détails de l'implémentation. Le Z80 n'étant pas particulièrement doué avec les files.
- la gestion de la balle (meilleur dessin, meilleur mouvement, meilleur rebond, etc.). Là encore, c'est un peu flou sur l'implémentation.
- comment gérer les niveaux, la création et le stockage des tableaux de briques. Toujours indécis si je dois utiliser un tableau ou une file.

hlide
Messages : 1706
Enregistré le : 29 nov. 2017 10:23

Re: [SHARP MZ-700] BRICK BUSTER

Message par hlide » 31 mai 2020 00:45

Légèrement hors-sujet mais pas tant que ça. Suite à mes calculs de cycles pour la version PAL, j'ai indiqué à MooZ, l'un des auteurs des démos sur MZ-700 qu'il pouvait dessiner jusqu'à 14 caractères par ligne (et donc 112 pixels par ligne). Il a donc crée un test et bingo !

Sous EmuZ-700 PAL, on obtient :
2020-05-31_00-19-40.png
2020-05-31_00-19-40.png (9.61 Kio) Vu 614 fois
Mais sous EmuZ-700 NTSC (on ne peut dessiner que 11 caractères par ligne), on obtient :
2020-05-31_00-19-55.png
2020-05-31_00-19-55.png (11 Kio) Vu 614 fois
Quoi du graphisme sous MZ-700, mais quelle est cette diablerie !?

C'est tout con, en fait : pour chaque ligne (de pixel), avant sa "rasterisation" à l'écran, on modifie les 14 caractères pour pouvoir présenter la ligne des 14 caractères ( ligne pixel d'écran modulo 8 ) et on le fait à chaque ligne de pixel de l'écran. Je ne connais pas le nom de cette technique mais je ne serais pas surpris que l'on retrouve sous différentes formes dans des machines plus capables.
Modifié en dernier par hlide le 31 mai 2020 11:28, modifié 1 fois.

petitjd
Messages : 1899
Enregistré le : 23 oct. 2007 11:50

Re: [SHARP MZ-700] BRICK BUSTER

Message par petitjd » 31 mai 2020 11:10

“Pouvoir de Jupiter, transforme moi!



Ok je sors, mais j’ai pas pu m’en empêcher :mrgreen:
PetitJD
Tortue Jeulin: www.tortue-jeulin.com
Nanoreseau: www.nanoreseau.net
Proteus III: www.proteus-international.fr

hlide
Messages : 1706
Enregistré le : 29 nov. 2017 10:23

Re: [SHARP MZ-700] BRICK BUSTER

Message par hlide » 31 mai 2020 11:35

Arf moi qui croyais qu'elle était brune !

hlide
Messages : 1706
Enregistré le : 29 nov. 2017 10:23

Re: [SHARP MZ-700] BRICK BUSTER

Message par hlide » 21 juin 2020 22:44

Bon reprenons les esprits.

Suite à un test sur le "color blending", j'ai pu constater que j'étais en mesure d'afficher un écran complet (40x25 carcatères et attributs, soit 2000 octets) en une trame via une routine qui transfère 10 octets par ligne pixel, soit 200 lignes en tout (sur 312). Ça m'amène à réfléchir sur la stratégie à prendre pour BrickBuster mais aussi pour d'autres jeux que j'espère faire à l'avenir. En effet, le code de la logique du jeu est très difficilement insérable entre deux dessins de ligne dans la période où il ne faut pas accéder à la VRAM (il n'y a que 137 cycles sur 228 par ligne).

L'affichage par ligne, m'impose pour être optimal de dessiner des octets contigus. C'est une sacrée contrainte que j'aimerais me débarrasser pour de futurs jeux où les "sprites" pourrait être des blocs et non des lignes. Mais pour BrickBuster dont l'essentiel des "sprites" restent des lignes à dessiner (briques 3x1, balle 1x1, rackette 6/9x1, score, etc.), j'aimerais aussi quand même m'affranchir de cette contrainte. D'autant que je prévoyais des éclairs verticaux et pas seulement horizontaux.

La zone de jeu de BrickBuster fait 32x25 en incluant la bordure. C'est 800 x 2 (caractère + attribut) octets à transférer en VRAM, soit environ 115 lignes pour 14 octets de transfert par ligne et ça prendrait moins de 37% du temps de la trame. Pour un jeu en surface 25x25, ça ferait 29%. Considérant le fait que transférer 14 octets par ligne n'est pas une chose facile à coder et qu'il serait plus simple de le faire avec 10 octets par ligne, ça nous ferait 160 lignes tout rond soit moins de 52% du temps de la trame. C'est chaud quand même.

Maintenant, si on considère l'usage d'un tampon en DRAM et d'une routine pour transférer ce tampon par trame, le fait de pouvoir dessiner dans ce tampon sans la contrainte du BLANK timing ne devrait-il pas considérablement accélérer le dessin globalement et permettre le dessin par bloc au lieu de ligne ?

Pour commencer, si je décide d'utiliser la même technique de dessin du tampon dans la VRAM par lot de 14 octets pour dessiner un fond dans le tampon, je vais avoir 2 x 32 x 25 / 14, soit 115 lots. Or un lot de 14 octets à transférer prend 175 cycles, j'aurais donc 20000 cycles, soit l'équivalent de 88 lignes ou 29% du temps de la trame. Pour dessiner le fond dans le tampon puis dessiner le tampon dans la VRAM, ça prendrait donc 65% du temps de la trame. Est-ce que 35% sera suffisant pour dessiner les "sprites" dans le tampon et gérer le reste de la logique du jeu ?

C'est très tentant cette technique de copie du tampon en VRAM pour la simplicité du reste.

Autre intérêt : le tampon pourrait faire 32x25 linéairement ou être en page de 256 octets par ligne.

La dernière option encapsulerait plus facilement le multi-buffering (quatre tampons). Soit DE l'adresse du tampon :
- Un INC D permet de passer à la ligne suivante.
- Un E dans l’intervalle [0, 32[ désignerait un des 32 caractères (RES 5,E) de la ligne du premier tampon (RES 6,E : RES 7,E).
- Un E dans l’intervalle [32, 64[ désignerait un des 32 attributs (SET 5,E) de la ligne du premier tampon (RES 6,E : RES 7,E).
- Un E dans l’intervalle [64, 95[ désignerait un des 32 caractères (RES 5,E) de la ligne du deuxième tampon (SET 6,E : RES 7,E).
- Un E dans l’intervalle [96, 127[ désignerait un des 32 attributs (SET 5,E) de la ligne du deuxième tampon (SET 6,E : RES 7,E).
- Un E dans l’intervalle [128, 159[ désignerait un des 32 caractères (RES 5,E) de la ligne du troisième tampon (RES 6,E : SET 7,E).
- Un E dans l’intervalle [160, 191[ désignerait un des 32 attributs (SET 5,E) de la ligne du troisième tampon (RES 6,E : SET 7,E).
- Un E dans l’intervalle [192, 223[ désignerait un des 32 caractères (RES 5,E) de la ligne du quatrième tampon (SET 6,E : SET 7,E).
- Un E dans l’intervalle [224, 255[ désignerait un des 32 attributs (SET 5,E) de la ligne du quatrième tampon (SET 6,E : SET 7,E).

Ou encore considérer une zone de 64x64 pour d'autres jeux au lieu de 32x25 pour avoir une vue dans un monde plus vaste avec défilements horizontaux et verticaux (et donc plus que 2 tampons au lieu de 4).

pour dessiner un bloc 3x3 :

Code : Tout sélectionner

draw_3x3_block:         ; cycles:
    LD      A,E         ;   4 = 4
    LDI                 ;  20 = 16 + 4
    LDI                 ;  36 = 16 + 20
    LDI                 ;  52 = 16 + 36
    INC     D           ;  56 = 4 + 52
    LD      E,A         ;  60 = 4 + 56
    LDI                 ;  76 = 16 + 60
    LDI                 ;  92 = 16 + 76
    LDI                 ; 108 = 16 + 92
    INC     D           ; 112 = 4 + 108
    LD      E,A         ; 116 = 4 + 112
    LDI                 ; 132 = 16 + 116
    LDI                 ; 148 = 16 + 132
    LDI                 ; 164 = 16 + 148
    RET                 ; 173 = 10 + 164
En comparaison, le même dessin à base de PUSH:POP en VRAM me prendrait trois lignes d'écran, soit 684 cycles.

Ah, j'oubliais ! et la couleur ?

Code : Tout sélectionner

draw_3x3_block: ; cycles: 357
    LD      B,D
    LD      C,E
    LD      A,32
    ADD     A,E
    LDI ; 1st line characters
    LDI
    LDI
    INC     D
    LD      E,C
    LDI ; 2nd line characters
    LDI
    LDI
    INC     D
    LD      E,C
    LDI ; 3rd line characters
    LDI
    LDI
    LD      D,B
    LD      E,A
    LDI ; 1st line attributes
    LDI
    LDI
    INC     D
    LD      E,A
    LDI ; 2nd line attributes
    LDI
    LDI
    INC     D
    LD      E,A
    LDI ; 3rd line attributes
    LDI
    LDI
    RET

Avatar du membre
6502man
Messages : 10098
Enregistré le : 12 avr. 2007 22:46
Localisation : VAR
Contact :

Re: [SHARP MZ-700] BRICK BUSTER

Message par 6502man » 24 juin 2020 22:21

Merci pour les détails techniques du développement :D

Tu n'est pas obligé de redessiner entièrement la zone de jeu à chaque trame, tu peux peut être te contenter de redessiner que la/les partie/s modifier par le trajet de la balle et divers animations, ca peux te faire gagner des cycles :wink:
Phil.

www.6502man.com

To bit or not to bit.
1 or 0.

Répondre