La Place des Développeurs Coder en C avec SDCC
ericb59
Membre non connecté
Conseiller Municipal
Reprise du message précédent
Citation :
the number of counts (NYB), when the screen edge is fetched
Qu'est-ce que cela veut dire au juste ?
ericb59 :
Qu'est-ce que cela veut dire au juste ?
Citation :
the number of counts (NYB), when the screen edge is fetched
Qu'est-ce que cela veut dire au juste ?
Je ne suis pas sûr, mais on peut en déduire que NY sert de compteur et qu'il vaut zéro à la fin de la commande.
MSX1: Daewoo DPC-200 / Yamaha CX5M
MSX2: Sony HB-F9P
MSXVR
Vidéo: V9990 (GFX-9)
Audio: MSX-Music (FM-PAC) / MSX-Audio (Audiowave) / OPL4 (Monster Sound FM Blaster) / OPNB (Neotron)
aoineko
Membre non connecté
Conseiller Municipal
ericb59 :
Qu'est-ce que cela veut dire au juste ?
Citation :
the number of counts (NYB), when the screen edge is fetched
Qu'est-ce que cela veut dire au juste ?
J'ai pas testé, mais de ce que j'avais compris c'est que normalement, SY est incrémenté de NY, et NY (qui sert de compteur) se retrouve à 0 (ou à 1 ?).
Mais si le bas de l'écran est rencontré avant la fin de la commande, les valeurs sont figées à ce moment là.
Y a un peu plus de détail dans la version de Eugeny Brychkov du V9938 Programmer’s Guide :
States of the registers after command execution
Setting up VDP registers for command execution is a significant task for programmer and CPU, and it will be wise to use already existing values in the registers for the next command execution or for further work with video memory. For this purpose programmer should know the resulting states of most important VDP registers. Please see the table below. Note that if program is going to use sequence of the VDP commands which use resulting values of registers from previous commands, it is important to disable interrupts so that interrupt handler routing would not accidentally change values in VDP registers and thus break the whole command sequence.
CMR H is a higher nibble of the command register R#46; CMR L is a lower nibble of the command register r#46. ARG is an argument register R#45.
The resulting values of SY*, DY* and NY* are in dots and can be calculated using equations below:
• If DIY=0 then SY*=SY+N; DY*=DY+N
• If DIY=1 then SY*=SY-N; DY*=DY-N
• NY*=NY-N
On est toujours ignorant avant de savoir.
Eugeny :
The resulting values of SY*, DY* and NY* are in dots and can be calculated using equations below:
• If DIY=0 then SY*=SY+N; DY*=DY+N
• If DIY=1 then SY*=SY-N; DY*=DY-N
• NY*=NY-N
• If DIY=0 then SY*=SY+N; DY*=DY+N
• If DIY=1 then SY*=SY-N; DY*=DY-N
• NY*=NY-N
En pratique, ce n'a pas beaucoup d'utilité ... Car même si les valeurs résultantes de SY et DY correspondent à ce que l'on veut pour la commande suivante, il faut quand même envoyer tous les autres paramètres (à moins qu'il soient absolument identiques). Edité par Metalion Le 23/01/2021 à 19h11
MSX1: Daewoo DPC-200 / Yamaha CX5M
MSX2: Sony HB-F9P
MSXVR
Vidéo: V9990 (GFX-9)
Audio: MSX-Music (FM-PAC) / MSX-Audio (Audiowave) / OPL4 (Monster Sound FM Blaster) / OPNB (Neotron)
Eugeny :
it is important to disable interrupts so that interrupt handler routing would not accidentally change values in VDP registers and thus break the whole command sequence
Par ailleurs, ce qu'il dit là est une précaution qui n'est pas forcément nécessaire ... L'ISR standard ne touche pas aux registres de commande du VDP. Par conséquent, à moins d'avoir mis dans son propre code une routine dépendant de l'ISR dans laquelle on lancerai une commande, il n'est pas utile de les protéger par DI/EI.
L'envoi de commande le plus rapide est ce bout de code écrit par Grauw :
Code :
;
; Faster again!!! DoCopy, by Grauw
; In: HL = pointer to 15-byte VDP command data
; Out: HL = updated
;
DoCopy:
ld a,32
di
out (#99),a
ld a,17+128
ei
out (#99),a
ld c,#9B
VDPready:
in a,(#99) ; loop if vdp not ready (CE)
rra
jp c,VDPready
outi ; 15x OUTI
outi ; (faster than OTIR)
outi
outi
outi
outi
outi
outi
outi
outi
outi
outi
outi
outi
outi
ret
Il y a moyen de faire encore plus rapide, en :
- basculant le registre de statut à 2 pendant toute la frame, pour le remettre à zéro uniquement pour l'ISR
- utilisant directement les registres si c'est possible (avec HMMV par exemple)
- en utilisant l'instruction "non-officielle" : out(c),0
MSX1: Daewoo DPC-200 / Yamaha CX5M
MSX2: Sony HB-F9P
MSXVR
Vidéo: V9990 (GFX-9)
Audio: MSX-Music (FM-PAC) / MSX-Audio (Audiowave) / OPL4 (Monster Sound FM Blaster) / OPNB (Neotron)
ericb59
Membre non connecté
Conseiller Municipal
@aoineko
J'ai besoin de l'aide d'un spécialiste du C... Y a un truc que je n'arrive pas à faire ...
Quand j'ai besoin de d'envoyer l'adresse d'une variable à une fonction je procède comme ceci
Actuellement j'ai la fonction ASM ci-après
Associé à 2 structures
BitmapFont me sert à décoder la font en ram, les données bitmap à afficher se trouvent au final, dans le tableau
Mtemp
d'où le ld hl,#_BitmapFont+5 dans le code ASM qui pointe vers l'adresse des datas à afficher.
La seconde structure stock les paramètres de la commande VDP
La structure comprend les 15 bytes à envoyer au VDP plus *adresse que je voudrais utiliser pour stocker l'adresse de mon pattern de 8x8 qui se trouve donc en _BitmapFont+5
Car, (a moins que je ne me trompe), à la fin des 15 OUTI de la routine ASM, HL devrait pointer ce sur dernier paramètre de ma structure VDPcmd à savoir *address
Mais ça ne marche pas.
Car je 'pense que je paramètre mal address et son assignation,
par exemple ma première idée était de faire comme ceci
VDPcmd.address=&BitmapFont.Mtemp;
Evidemment ca ne marche pas....
j'ai essayé plusieurs possibilités, mais je dois louper quelque chose...
Edité par ericb59 Le 24/01/2021 à 09h31
J'ai besoin de l'aide d'un spécialiste du C... Y a un truc que je n'arrive pas à faire ...
Quand j'ai besoin de d'envoyer l'adresse d'une variable à une fonction je procède comme ceci
Code C :
void mafonction (void *addresse) __z88dk_fastcall __naked { __asm ; address est directement dans HL __endasm; } unsigned int Variable= 65535; void main(void) { mafonction (&Variable); }
Actuellement j'ai la fonction ASM ci-après
Code C :
// Fast VDP use of LMMM or HMMM for 8x8 pattern void FastChar(void *Params) __z88dk_fastcall __naked { Params; __asm di fvdpWait1: ld a,#2 out (#0x99),a ld a,#128+#15 out (#0x99),a in a,(#0x99) rrca jp c, fvdpWait1 ; wait CE ld a,#32 ; Start with Reg 32 out (#0x99),a ld a,#128+#17 out (#0x99),a ;R#17 := 32 ld bc,#0x0f9b ; c=9b b=0f OUTI OUTI OUTI OUTI OUTI OUTI OUTI OUTI OUTI OUTI OUTI OUTI OUTI OUTI OUTI ld a,#128+#44 out (#0x99),a ld a,#128+#17 out (#0x99),a ; VDP(17)<=44 ld hl,#_BitmapFont+5 ld b,#64 ; Number of bytes to send otir ;exit xor a out (#0x99),a ld a,#0x8f ei out (#0x99),a ret __endasm; }
Associé à 2 structures
Code C :
typedef struct { char letter_data; unsigned int x; unsigned int y; char Mtemp[8][8]; char TabColor[16][4]; char letter; unsigned int letter_addr; } GraphPrint; GraphPrint BitmapFont;
BitmapFont me sert à décoder la font en ram, les données bitmap à afficher se trouvent au final, dans le tableau
Mtemp
d'où le ld hl,#_BitmapFont+5 dans le code ASM qui pointe vers l'adresse des datas à afficher.
La seconde structure stock les paramètres de la commande VDP
Code C :
typedef struct { unsigned int sx; // source X (0 to 511) R32 & R33 unsigned int sy; // source Y (0 to 1023) R34 & R34 unsigned int dx; // destination X (0 to 511) R36 & R37 unsigned int dy; // destination Y (0 to 1023) R38 & R39 unsigned int nx; // width (0 to 511) R40 & R41 unsigned int ny; // height (0 to 511) R42 & R43 unsigned char col; // color used by some commands. R44 unsigned char param; // Parameters set the direction. Example opDOWN | opRIGHT R45 unsigned char cmd; // VDP Command + Logical Operator : Like opLMMM | LOGICAL_XOR R46 void *address; } FastVDP; FastVDP VDPcmd;
La structure comprend les 15 bytes à envoyer au VDP plus *adresse que je voudrais utiliser pour stocker l'adresse de mon pattern de 8x8 qui se trouve donc en _BitmapFont+5
Car, (a moins que je ne me trompe), à la fin des 15 OUTI de la routine ASM, HL devrait pointer ce sur dernier paramètre de ma structure VDPcmd à savoir *address
Mais ça ne marche pas.
Car je 'pense que je paramètre mal address et son assignation,
par exemple ma première idée était de faire comme ceci
VDPcmd.address=&BitmapFont.Mtemp;
Evidemment ca ne marche pas....
j'ai essayé plusieurs possibilités, mais je dois louper quelque chose...
Edité par ericb59 Le 24/01/2021 à 09h31
ericb59
Membre non connecté
Conseiller Municipal
@metalion
Sans DI/EI mes routines VDP ont toujours plantée... Peut être parceque j'utilise SDCC ?
Comment la routine de grauw arrive à lire le registre #2 sans avoir préalablement mis #2 dans le registre R#15 ? tel qu'on est censé le faire ?
De plus il ne réinitialise pas à 0 à la fi, de la procédure. Est-ce optionnel ? Edité par ericb59 Le 24/01/2021 à 09h47
Sans DI/EI mes routines VDP ont toujours plantée... Peut être parceque j'utilise SDCC ?
Comment la routine de grauw arrive à lire le registre #2 sans avoir préalablement mis #2 dans le registre R#15 ? tel qu'on est censé le faire ?
De plus il ne réinitialise pas à 0 à la fi, de la procédure. Est-ce optionnel ? Edité par ericb59 Le 24/01/2021 à 09h47
aoineko
Membre non connecté
Conseiller Municipal
ericb59 :
@metalion
Sans DI/EI mes routines VDP ont toujours plantée... Peut être parceque j'utilise SDCC ?
Comment la routine de grauw arrive à lire le registre #2 sans avoir préalablement mis #2 dans le registre R#15 ? tel qu'on est censé le faire ?
De plus il ne réinitialise pas à 0 à la fi, de la procédure. Est-ce optionnel ?
Sans DI/EI mes routines VDP ont toujours plantée... Peut être parceque j'utilise SDCC ?
Comment la routine de grauw arrive à lire le registre #2 sans avoir préalablement mis #2 dans le registre R#15 ? tel qu'on est censé le faire ?
De plus il ne réinitialise pas à 0 à la fi, de la procédure. Est-ce optionnel ?
C'est pas un problème de SDCC mais un problème de l'ISR par défaut (la routine qui gère les interruptions).
Elle check l'état du registre de status S#0 sans setté ce registre (un archaïsme venant du MSX1 je suppose) donc ça peut poser problème si l'ISR arrive à un moment ou tu as changé le registre de status.
Dans ce cas le DI/EI est nécessaire.
Idem quand une fonctionnalité du VDP nécessite l'utilisation consécutive 2 registres.
L'ISR pouvant avoir lieu entre l'accès à ces 2 registres, il faut protéger ce code contre les interruption.
Ensuite, tout dépend de ce que ton programme fait dans les hook H.KEYI et H.TIMI.
Si jamais tu accèdes au VDP dans ces hook, tu devras prendre plus de précautions dans le reste de ton code et potentiellement protéger certains bouts de code.
Pour l'autre question c'est pas simple d'assimiler toutes les infos... je vais relire.
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
-Dans mes tests VDP il n’y a aucune interruption d’activée.
- pour la première question, en gros : comment stocker l’adresse d’un tableau contenu dans une structure (ou juste l’adresse de la structure) , dans une autre structure qui elle est envoyée au programme ASM.
- pour la première question, en gros : comment stocker l’adresse d’un tableau contenu dans une structure (ou juste l’adresse de la structure) , dans une autre structure qui elle est envoyée au programme ASM.
aoineko
Membre non connecté
Conseiller Municipal
ericb59 :
-Dans mes tests VDP il n’y a aucune interruption d’activée.
A part celle du système (à moins que tu es installé ton propre ISR).
ericb59 :
- pour la première question, en gros : comment stocker l’adresse d’un tableau contenu dans une structure (ou juste l’adresse de la structure) , dans une autre structure qui elle est envoyée au programme ASM.
VDPcmd.address=&BitmapFont.Mtemp; devrait fonctionner.
Quand j'affiche les adresses dans un sample, j'ai C002h pour &BitmapFont et C007h pour &BitmapFont.Mtemp (donc bien le +5).
On est toujours ignorant avant de savoir.
ericb59 :
@metalion
Sans DI/EI mes routines VDP ont toujours plantée... Peut être parceque j'utilise SDCC ?
Sans DI/EI mes routines VDP ont toujours plantée... Peut être parceque j'utilise SDCC ?
Je parlais de DI/EI sur l'envoi des registres 32 à 46.
Il faut évidemment conserver un DI/EI sur la mise en place de l'écriture séquentielle, au début.
Mais pas sur les OUTI/OTIR.
ericb59 :
Comment la routine de grauw arrive à lire le registre #2 sans avoir préalablement mis #2 dans le registre R#15 ? tel qu'on est censé le faire ?
De plus il ne réinitialise pas à 0 à la fin de la procédure. Est-ce optionnel ?
De plus il ne réinitialise pas à 0 à la fin de la procédure. Est-ce optionnel ?
Je me suis trompé, j'ai recopié sa routine optimisée pour le registre de statut toujours à 2 ... J'utilise aussi cette optimisation. Il suffit de mettre le registre de statut à 0 lors de l'appel à H.KEYI, et de le rétablir à 2 lors de l'appel à H.TIMI. De cette façon, le registre de statut est toujours à 2 pendant la frame.
MSX1: Daewoo DPC-200 / Yamaha CX5M
MSX2: Sony HB-F9P
MSXVR
Vidéo: V9990 (GFX-9)
Audio: MSX-Music (FM-PAC) / MSX-Audio (Audiowave) / OPL4 (Monster Sound FM Blaster) / OPNB (Neotron)
aoineko
Membre non connecté
Conseiller Municipal
Metalion :
Je me suis trompé, j'ai recopié sa routine optimisée pour le registre de statut toujours à 2 ... J'utilise aussi cette optimisation. Il suffit de mettre le registre de statut à 0 lors de l'appel à H.KEYI, et de le rétablir à 2 lors de l'appel à H.TIMI. De cette façon, le registre de statut est toujours à 2 pendant la frame.
C'est tout simple mais ça doit faire gagner pas mal de temps
C'est p'être pas forcement l'endroit pour en discuter, mais tu as gardé l'ISR par défaut de l'OS !?
Vu les prouesses que tu as fais avec ton Out-Run, j'aurai imaginé que tu étais sur un ISR custom.
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
aoineko :
VDPcmd.address=&BitmapFont.Mtemp; devrait fonctionner.
Quand j'affiche les adresses dans un sample, j'ai C002h pour &BitmapFont et C007h pour &BitmapFont.Mtemp (donc bien le +5).
VDPcmd.address=&BitmapFont.Mtemp; devrait fonctionner.
Quand j'affiche les adresses dans un sample, j'ai C002h pour &BitmapFont et C007h pour &BitmapFont.Mtemp (donc bien le +5).
Ben ca ne marche pas.
Je te mets là le programme de test complet, et autonome
tu peux le compiler sans librairie particulière
J'ai indiqué lisiblement là où se trouve mon problème.
font2.c.zip
aoineko
Membre non connecté
Conseiller Municipal
Je galère à essayer de compiler/build ton code.
En tout cas, je vois aucune raison pour laquelle ld hl,#_BitmapFont+5 ne fonctionnerait pas.
Tu as débuggé avec OpenMSX pour voir la valeur que prends HL ?
A mon avis, ton problème est ailleurs.
En tout cas, je vois aucune raison pour laquelle ld hl,#_BitmapFont+5 ne fonctionnerait pas.
Tu as débuggé avec OpenMSX pour voir la valeur que prends HL ?
A mon avis, ton problème est ailleurs.
On est toujours ignorant avant de savoir.
aoineko
Membre non connecté
Conseiller Municipal
Je pense pas que le problème vienne de là, mais voici quelques commentaires :
J'ai noté les endroits ou il faut interrompre les interruptions.
Ca marche aussi si tu ne gardes que le premier et le dernier, mais ça va limiter la possibilité pour tes utilisateurs de faire du screen split.
Code ASM :
di fvdpWait1: ld a,#2 ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DI out (#0x99),a ld a,#128+#15 out (#0x99),a ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EI in a,(#0x99) rrca jp c, fvdpWait1 ; wait CE ld a,#32 ; Start with Reg 32 ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DI out (#0x99),a ld a,#128+#17 ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EI out (#0x99),a ;R#17 := 32 ld bc,#0x0f9b ; c=9b b=0f // [Aoineko] : Comme tu fais des outi, tu n'as pas besoin de set B et C (tu as besoin de C ensuite par contre) OUTI OUTI OUTI OUTI OUTI OUTI OUTI OUTI OUTI OUTI OUTI OUTI OUTI OUTI OUTI ; [Aoineko] : Tu peux remplacer ces 15 outi par : ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DI ; .rept 14 ; outi ; .endm ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EI ; outi ld a,#128+#44 ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DI out (#0x99),a ld a,#128+#17 ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EI out (#0x99),a ; VDP(17)<=44 //------------- PROBLEM -------------------------------- // ICI HL devrait avoir le contenu de BitmapFont.Mtemp // C'est à dire l'addresse du tablau Mtemp où sont les données Bitmpa à afficher. // Enlève le commentaire de la ligne suivante pour voir le résultat que je veux avoir //ld hl,#_BitmapFont+5 ;// [Aoineko] : Set C à 9Bh ld b,#64 ; Number of bytes to send // [Aoineko] : Avec la commande LMMC, le premier byte est envoyé dans FastVDP.col. Du coup, il ne te reste que 63 bytes à envoyer ensuite otir ;exit xor a ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DI out (#0x99),a ld a,#0x8f ei ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EI out (#0x99),a ret
J'ai noté les endroits ou il faut interrompre les interruptions.
Ca marche aussi si tu ne gardes que le premier et le dernier, mais ça va limiter la possibilité pour tes utilisateurs de faire du screen split.
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
aoineko :
Je galère à essayer de compiler/build ton code.
En tout cas, je vois aucune raison pour laquelle ld hl,#_BitmapFont+5 ne fonctionnerait pas.
Tu as débuggé avec OpenMSX pour voir la valeur que prends HL ?
A mon avis, ton problème est ailleurs.
En tout cas, je vois aucune raison pour laquelle ld hl,#_BitmapFont+5 ne fonctionnerait pas.
Tu as débuggé avec OpenMSX pour voir la valeur que prends HL ?
A mon avis, ton problème est ailleurs.
Ben ? Pourquoi tu galère ? Y a rien de spécial dans mon code !
Je crois que je me suis mal fait comprendre ...
ld hl,#_BitmapFont+5, Fonctionne.
Ce que je veux, c’est me passer de cet appel à une variable,
Mais faire en sorte que HL pointe vers les données en ayant stockée l’adresse dans VDPcmd.adress
(Le fait d’avoir un nom de variable fixé dans mon code ASM, n’est pas assez généraliste pour fusion-c.)
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie