MSX Village forum

La Place des Développeurs Coder en C avec SDCC

ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5571

Le 23/01/2021 à 16h05

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 ? :hum


banniere-ericb59e
Site web    
Metalion Membre non connecté

Conseiller Municipal

Rang

Avatar

Inscrit le : 23/12/2009 à 15h32

Messages: 1503

Le 23/01/2021 à 18h14
ericb59 :
Citation :
the number of counts (NYB), when the screen edge is fetched


Qu'est-ce que cela veut dire au juste ? :hum

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

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2914

Le 23/01/2021 à 18h22
ericb59 :
Citation :
the number of counts (NYB), when the screen edge is fetched

Qu'est-ce que cela veut dire au juste ? :hum


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.
Github    
Metalion Membre non connecté

Conseiller Municipal

Rang

Avatar

Inscrit le : 23/12/2009 à 15h32

Messages: 1503

Le 23/01/2021 à 19h10
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

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)
   
Metalion Membre non connecté

Conseiller Municipal

Rang

Avatar

Inscrit le : 23/12/2009 à 15h32

Messages: 1503

Le 24/01/2021 à 09h04
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

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5571

Le 24/01/2021 à 09h17
@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
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


banniere-ericb59e
Site web    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5571

Le 24/01/2021 à 09h42
@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


banniere-ericb59e
Site web    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2914

Le 24/01/2021 à 11h36
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 ?


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. :p


On est toujours ignorant avant de savoir.
Github    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5571

Le 24/01/2021 à 11h59
-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.


banniere-ericb59e
Site web    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2914

Le 24/01/2021 à 12h12
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.
Github    
Metalion Membre non connecté

Conseiller Municipal

Rang

Avatar

Inscrit le : 23/12/2009 à 15h32

Messages: 1503

Le 24/01/2021 à 12h14
ericb59 :
@metalion
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 ?

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

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2914

Le 24/01/2021 à 12h29
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 :love

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.
Github    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5571

Le 24/01/2021 à 20h05
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).


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


banniere-ericb59e
Site web    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2914

Le 24/01/2021 à 20h49
Je galère à essayer de compiler/build ton code. :moue
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.
Github    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2914

Le 24/01/2021 à 21h06
Je pense pas que le problème vienne de là, mais voici quelques commentaires :

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.
Github    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5571

Le 24/01/2021 à 22h32
aoineko :
Je galère à essayer de compiler/build ton code. :moue
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.)



banniere-ericb59e
Site web    
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie