La Place des Développeurs Projet GOS Et oui, encore trop d'ambitions ^^
aoineko
Membre non connecté
Conseiller Municipal
Reprise du message précédent
Vu qu'il n'y a pas (à ma connaissance) de hook pour la de gestion des H-Blank, je check le flag qui le gère dans le hook H.KEYI.Le problème c'est que dans le mode d'interruption par défaut (IM1), toutes les interruptions passe par le même code (38h) donc la quantité de code qu'il y a entre le début de l'interruption et l'exécution du hook H.KEYI et le même que l'interruption ait été déclenché par le H-Blank ou le V-Blank.
Je sais pas si en mode IM2 le VDP nous renverrai un code différent pour ces deux interruptions ?
Si c'est le cas, on pourrait géré ces cas séparément sans que la gestion de l'un ne ralentisse celle de l'autre.
L'autre solution c'est de remplacer le code de gestion en 38h (c'est mon but) pour avoir quelque chose de plus optimal pour un jeu (en gros, ne check que les flags du VDP).
On est toujours ignorant avant de savoir.
pas testé sur MSX1 car quand j'ai mis le programme dans une flashrom avec OPF en le lançant par reset écran noir
j'ai vu ensuite que j'avait vérolé ma compactflash illisible
du coup formatage et remis les programmes dedans
je vais en dédier une petite uniquement aux test
celle que j'ai sera pour les jeux en ROM uniquement
j'ai vu ensuite que j'avait vérolé ma compactflash illisible
du coup formatage et remis les programmes dedans
je vais en dédier une petite uniquement aux test
celle que j'ai sera pour les jeux en ROM uniquement
aoineko :
Vu qu'il n'y a pas (à ma connaissance) de hook pour la de gestion des H-Blank, je check le flag qui le gère dans le hook H.KEYI.
Le problème c'est que dans le mode d'interruption par défaut (IM1), toutes les interruptions passe par le même code (38h) donc la quantité de code qu'il y a entre le début de l'interruption et l'exécution du hook H.KEYI et le même que l'interruption ait été déclenché par le H-Blank ou le V-Blank.
Le problème c'est que dans le mode d'interruption par défaut (IM1), toutes les interruptions passe par le même code (38h) donc la quantité de code qu'il y a entre le début de l'interruption et l'exécution du hook H.KEYI et le même que l'interruption ait été déclenché par le H-Blank ou le V-Blank.
Il n'y a pas tant de code que ça avant l'appel du hook. Voici le code BIOS appelé par $38 :
PUSH HL
PUSH DE
PUSH BC
PUSH AF
EXX
EX AF,AF'
PUSH HL
PUSH DE
PUSH BC
PUSH AF
PUSH IY
PUSH IX
CALL H.KEYI
IN A,(VDP.SR)
AND A
JP P,INTRET
CALL H.TIMI
PUSH DE
PUSH BC
PUSH AF
EXX
EX AF,AF'
PUSH HL
PUSH DE
PUSH BC
PUSH AF
PUSH IY
PUSH IX
CALL H.KEYI
IN A,(VDP.SR)
AND A
JP P,INTRET
CALL H.TIMI
Comme tu peux le voir H.KEYI est appelé tout de suite (et est donc appelé pour toute interruption, VDP ou non). C'est effectivement le bon hook pour les interruptions HBLANK (le hook H.TIMI n'est appelé uniquement que dans le cas d'une interruption VBLANK du VDP).
Déjà, la sauvegarde de tous les registres (et leur restauration à la sortie) prends 266 cycles, soit un peu plus d'une ligne ... Edité par Metalion Le 13/01/2021 à 17h36
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
Après, faut ajouter le check du bit #0 de S#1 dans mon hook H.KEYI, le saut vers ma fonction de gestion du H-Blank puis le code assembleur de cette fonction C.
Elle est pas très compliqué donc ça explique difficilement les 4 lignes de décalage en version ROM... et encore plus difficilement les 10 lignes de décalage sous DOS !
J'ai essayé de retirer tous les updates que je faisais durant la frame pour faire bouger mes sprites, mais ça change absolument rien (de toute façon, je minimise vraiment les temps de DI).
Du coup... aucune idée d'où peu venir se décalage variable en fonction de l'OS...
Pour info, ma fonction C qui gère le H-Blank (ça me semble pas trop dégueu pour du code compilé )
Les sprites sont en 16x16 scale 1 dans la partie haute de l'écran, 16x16 x2 au milieu et 8x8 x1 en bas.
Elle est pas très compliqué donc ça explique difficilement les 4 lignes de décalage en version ROM... et encore plus difficilement les 10 lignes de décalage sous DOS !
J'ai essayé de retirer tous les updates que je faisais durant la frame pour faire bouger mes sprites, mais ça change absolument rien (de toute façon, je minimise vraiment les temps de DI).
Du coup... aucune idée d'où peu venir se décalage variable en fonction de l'OS...
Pour info, ma fonction C qui gère le H-Blank (ça me semble pas trop dégueu pour du code compilé )
Code ASM :
_HBlankHook:: ld l, #0x00 call _VDP_SetColor ; VDP_SetColor(0); ld a,(#_g_Phase + 0) or a, a jr NZ,00102$ ; if(g_Phase == 0) ld l, #0x03 call _VDP_SetSpriteFlag ; VDP_SetSpriteFlag(VDP_SPRITE_SIZE_16 + VDP_SPRITE_SCALE_2); ld l, #0x71 call _VDP_SetHBlankLine ; VDP_SetHBlankLine(SPRITE_8_LINE); ld iy, #_g_Phase inc 0 (iy) ; g_Phase++; ld l, #0x0c jp _VDP_SetColor ; VDP_SetColor(12); 00102$: ld l, #0x00 call _VDP_SetSpriteFlag ; VDP_SetSpriteFlag(VDP_SPRITE_SIZE_8); ld l, #0x06 jp _VDP_SetColor ; VDP_SetColor(6); 00104$: ret
Les sprites sont en 16x16 scale 1 dans la partie haute de l'écran, 16x16 x2 au milieu et 8x8 x1 en bas.
On est toujours ignorant avant de savoir.
4 lignes, cela fait 912 cycles.
Si on retire les 266 cycles pour les registres, il reste 646 cycles soit 80 instructions (en moyenne).
Ce n'est pas grand chose et cela peut aller très vite, donc cela ne m'étonne pas fondamentalement.
10 lignes sous DOS, c'est un peu plus long effectivement, mais je ne connais pas bien ce que fait l'ISR du DOS.
Ceci dit, l'avantage du DOS, c'est qu'il te reste toujours la possibilité de réécrire toi-même l'ISR pour qu'elle soit plus rapide.
Si on retire les 266 cycles pour les registres, il reste 646 cycles soit 80 instructions (en moyenne).
Ce n'est pas grand chose et cela peut aller très vite, donc cela ne m'étonne pas fondamentalement.
10 lignes sous DOS, c'est un peu plus long effectivement, mais je ne connais pas bien ce que fait l'ISR du DOS.
Ceci dit, l'avantage du DOS, c'est qu'il te reste toujours la possibilité de réécrire toi-même l'ISR pour qu'elle soit plus rapide.
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 :
Ceci dit, l'avantage du DOS, c'est qu'il te reste toujours la possibilité de réécrire toi-même l'ISR pour qu'elle soit plus rapide.
C'est bien mon objectif à moyen termes.
J'attends d'avoir complété ma lib (ce qui est pas loin d'être le cas), puis je couperai le cordon ombilical avec le Bios.
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
@aoineko j'ai vu dans ta lib, des fonctions qui font appel au BIOS pour récupérer des infos tels que la taille des sprites et autres petites choses qui sont en fait dispo dans les variables système.
Mais je suppose qu'il y a une raison pour laquelle tu as gardé ces fonctions dans ta lib.
je mets une liste ici, au cas ou ça serve à quelqu'un
Mais je suppose qu'il y a une raison pour laquelle tu as gardé ces fonctions dans ta lib.
je mets une liste ici, au cas ou ça serve à quelqu'un
Code C :
#define IsVsync() ((VDPstatusNi( 0 ) & 0x80) != 0) #define IsHsync() ((VDPstatusNi( 1 ) & 0x01) != 0) #define _SpriteOn (((*(char *)0xFFE7) >> 1) & 0x01) // Returns 0 when sprites are activated, 1 when sprites are desactivated #define _SpriteSize (((*(char *)0xF3E0) >> 1) & 0x01) // Returns 0 when sprite size is 8x8, 1 when size is 16x16 #define _SpriteMag (((*(char *)0xF3E0)) & 0x01) // Returns 0 when Mag is simple, 1 when sprite are double #define _ActivePage (*(char *)0xFAF6) // Returns the active VRAM Page (MSX2) #define _DisplayPage (*(char *)0xFAF5) // Returns the displayed VRAM Page (MSX2) #define _VDPfreq (((*(char *)0xFFE8) >> 1) & 0x01) // Returns 1 for 50 Hz, 0 for 60 Hz (MSX2) #define _VDPlines (((*(char *)0xFFE8) >> 7) & 0x01) // Returns 1 for 212 lines, 0 for 192 lines (MSX2) #define _ForegroundColor (*(char *)0xF3E9) // Returns the foreground color #define _BackgroundColor (*(char *)0xF3EA) // Returns the background color #define _BorderColor (*(char *)0xF3EB) // Returns the border color #define _ScreenMode (*(char *)0xFCAF) // Returns the actual Screen mode #define _SpritePatternAddr (*( (volatile unsigned int*)(0xF926))) // Returns Default Sprite Pattern table Address in Vram for the current screen mode #define _SpriteAttribAddr (*( (volatile unsigned int*)(0xF928))) // Returns Default Sprite attributs table Address in Vram for the current screen mode #define _SpriteColorAddr ((*( (volatile unsigned int*)(0xF928)))-512) // Returns Default Sprite colors table Address in Vram for the current screen mode (MSX2 & upper only) #define _WidthScreen0 (*(char *)0xF3AE) // Returns the actual Screen width for screen mode 0 #define _WidthScreen1 (*(char *)0xF3AF) // Returns the actual Screen width for screen mode 1 #define _Time (*(unsigned int *)0xFC9E) // Returns Current MSX TImer 0..65535 #define _FusionVer (char)13 // Fusion-C Version (Divide by 10 to understand version number) #define _FusionRev (unsigned int)11211 // Fusion-C last Revision Date First digit is number of year after 2019. 2 next digits is day of revision, 2 last digits are month of revision
aoineko
Membre non connecté
Conseiller Municipal
Toujours la même raison... pouvoir se débarrasser un jour du Bios.
Mais je vais laissé la possibilité de garder le Bios (ça peut être pratique pour certain programme) donc la plupart des variables de la Work area de l'OS seront toujours utilisables.
Comme pour beaucoup de chose dans ma lib, j'ajouterai un define qui dira au moment du build si on garde le Bios ou si on le remplace (ce qui modifiera le crt0 et les fonctions disponibles).
Mais pour ce qui est du traitement du VDP, je pense que je vais laissé uniquement ma version dans tous les cas.
Mais je vais laissé la possibilité de garder le Bios (ça peut être pratique pour certain programme) donc la plupart des variables de la Work area de l'OS seront toujours utilisables.
Comme pour beaucoup de chose dans ma lib, j'ajouterai un define qui dira au moment du build si on garde le Bios ou si on le remplace (ce qui modifiera le crt0 et les fonctions disponibles).
Mais pour ce qui est du traitement du VDP, je pense que je vais laissé uniquement ma version dans tous les cas.
On est toujours ignorant avant de savoir.
aoineko
Membre non connecté
Conseiller Municipal
C'est surtout pour Ericb, mais je post ici au cas ou ça puisse également intéresser quelqu'un d'autre.
J'ai fini ma lib de Print et tout est publié sur GitHub : https://github.com/aoineko-fr/cmsx
Voici les fonctionnalités :
- 3 modes de rendu : RAMtoVRAM, VRAMtoVRAM et Sprites.
- 2 modes couleurs : monochrome ou 1 couleur par ligne.
- 2 effets : shadow (ombrage) et outline (détourage).
- Taille de pattern variable (8 px max en largeur)
- Screen modes supportés : Screen 5, 6, 7 et 8.
Le tout est configurable via des defines qui permettent d'avoir, selon les besoins, soit un code bien optimisé, soit beaucoup de fonctionnalités.
Il me reste un truc bizarre avec les sprites à régler.
Pour les tables de pattern/attribute, j'ai parfois des soucis quand je les places au-delà de 10000h (même si je respecte le multiple spécifique à chaque table).
Faut que je vois s'il a des limitations que je ne connais pas ou si c'est juste un bug dans mon code.
Ensuite je vais passer au player music/sfx et je devrais avoir tout ce qu'il me faut pour le projet GOS.
J'ai fini ma lib de Print et tout est publié sur GitHub : https://github.com/aoineko-fr/cmsx
Voici les fonctionnalités :
- 3 modes de rendu : RAMtoVRAM, VRAMtoVRAM et Sprites.
- 2 modes couleurs : monochrome ou 1 couleur par ligne.
- 2 effets : shadow (ombrage) et outline (détourage).
- Taille de pattern variable (8 px max en largeur)
- Screen modes supportés : Screen 5, 6, 7 et 8.
Le tout est configurable via des defines qui permettent d'avoir, selon les besoins, soit un code bien optimisé, soit beaucoup de fonctionnalités.
Il me reste un truc bizarre avec les sprites à régler.
Pour les tables de pattern/attribute, j'ai parfois des soucis quand je les places au-delà de 10000h (même si je respecte le multiple spécifique à chaque table).
Faut que je vois s'il a des limitations que je ne connais pas ou si c'est juste un bug dans mon code.
Ensuite je vais passer au player music/sfx et je devrais avoir tout ce qu'il me faut pour le projet GOS.
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
Super !
T'as oublié une option :
La redéfinissions des caractères dans les mode 0 à 4.
Bon, c'est trivial, il suffit de faire un Copy Ram to Vram, c'est juste pour chipoter
T'as oublié une option :
La redéfinissions des caractères dans les mode 0 à 4.
Bon, c'est trivial, il suffit de faire un Copy Ram to Vram, c'est juste pour chipoter
aoineko :
Il me reste un truc bizarre avec les sprites à régler.
Pour les tables de pattern/attribute, j'ai parfois des soucis quand je les places au-delà de 10000h (même si je respecte le multiple spécifique à chaque table).
Faut que je vois s'il a des limitations que je ne connais pas ou si c'est juste un bug dans mon code.
Pour les tables de pattern/attribute, j'ai parfois des soucis quand je les places au-delà de 10000h (même si je respecte le multiple spécifique à chaque table).
Faut que je vois s'il a des limitations que je ne connais pas ou si c'est juste un bug dans mon code.
J'ai déjà eu ce problème ... Impossible de placer les tables au delà de 10000h, ça plantait.
Et je n'ai jamais trouvé la cause. J'ai vérifié tellement de fois les valeurs des registres que ça me rendait fou.
Finalement, j'ai abandonné, et j'ai réorganisé la VRAM pour pouvoir mettre ces tables avant 10000h.
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 :
T'as oublié une option :
La redéfinissions des caractères dans les mode 0 à 4.
La redéfinissions des caractères dans les mode 0 à 4.
J'avance en fonction de mes besoins. Et pour le moment j'ai pas besoin des modes textes.
Au fait, par rapport aux questions sur la vitesse des routines RAM to VRAM, j'ai trouvé une solution plus rapide : Je décode un caractère complet dans un buffer en RAM avant de l'envoyer d'un coup en VRAM. Je comprends pas vraiment pourquoi c'est plus rapide, mais c'est le cas.
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
Citation :
Je décode un caractère complet dans un buffer en RAM avant de l'envoyer d'un coup en VRAM.
J'avais testé ça aussi, en utilisant HMMC, mais j'ai pas trouvé que c'était plus rapide. Avec une routine RamToVram, c'est peut être plus rapide, mais dans ce cas, comment formater les données pour avoir un seul bloc de 8x8 non linéaire ?
aoineko
Membre non connecté
Conseiller Municipal
Metalion :
J'ai déjà eu ce problème ... Impossible de placer les tables au delà de 10000h, ça plantait.
Et je n'ai jamais trouvé la cause. J'ai vérifié tellement de fois les valeurs des registres que ça me rendait fou.
Finalement, j'ai abandonné, et j'ai réorganisé la VRAM pour pouvoir mettre ces tables avant 10000h.
Et je n'ai jamais trouvé la cause. J'ai vérifié tellement de fois les valeurs des registres que ça me rendait fou.
Finalement, j'ai abandonné, et j'ai réorganisé la VRAM pour pouvoir mettre ces tables avant 10000h.
Argh... ça sape un peu mes espoirs.
Surtout que j'ai vérifié que la bonne valeur était bien envoyé au VDP (via le debugger de OpenMSX).
Et j'ai rien trouvé dans la doc du V9938 non plus.
Mais bon, je vais continuer à creuser.
ericb59 :
J'avais testé ça aussi, en utilisant HMMC, mais j'ai pas trouvé que c'était plus rapide. Avec une routine RamToVram, c'est peut être plus rapide, mais dans ce cas, comment formater les données pour avoir un seul bloc de 8x8 non linéaire ?
Avec HMMC, ta source doit être linéaire ; c'est la commande VDP s'occupe de split les datas par lignes.
Du coup, tu as juste besoin de décoder ton pattern dans un buffer de taille W x H avec :
- W qui représente le nombre d'octets d'une ligne ; donc ça dépend de la largeur du pattern et du nombre de bit-par-couleur du mode. Par exemple, pour une font avec des patterns de 6 points de large pour le mode G4 (Screen 5) qui est en 4 BPC, tu as besoin de 3 octets par ligne,
- H qui représente le nombre de lignes (pas forcement 8 ; sauf pour le mode d'affichage via les sprites).
Ensuite un seul HMMC sur ce buffer suffit à placer les données d'un caractère en VRAM.
J'utilise la technique à la fois pour afficher du texte sur l'écran visible, et aussi pour mon mode d'affichage VRAMtoVRAM to initialiser la font en VRAM.
A noter aussi que j'utilise la commande VDP PSET pour l'affichage pour les modes ou j'ai besoin de la transparence (notamment les effets de Shadow/Outline).
J'avais essayé avec LMMC, mais c'est trop lourd à mettre en place (cette commande fonctionne avec 1 octet par couleur quelque soit le mode graphique) et le gain était minime.
EDIT : Ah, je crois que j'ai mal compris ta question. Si tu utilises une fonction d'écriture "directe" vers la VRAM, elle ne peux pas gérer les splits par ligne. C'est tout l'intérêt de HMMC. Donc dans le cas de l'écriture directe, le mieux est d'envoyer les paquets ligne par ligne. Même si la copie est aussi rapide via une écriture directe (voir p'être plus rapide), tu perds beaucoup de temps en setup et en call de ta fonction à chaque ligne. C'est surement pour cette raison qu'un HMMC unique est (légèrement) plus rapide.
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
Oui, oui, je sais utiliser HMMC.
Je l’avais fait pour un affichage caractère par caractère.
Mais je ne gagnais pas de temps comparé à l’affichage ligne par ligne du CopyRam2Vram... ce qui m’avait surpris !
La différence est peut être sur le setup de ta commande HMMC, je vais regarder comment tu l’a mise en place.
Pour le mode transparent, je l’avais fait LMMC, c’est un peut plus lent que HMMC.
Je l’avais fait pour un affichage caractère par caractère.
Mais je ne gagnais pas de temps comparé à l’affichage ligne par ligne du CopyRam2Vram... ce qui m’avait surpris !
La différence est peut être sur le setup de ta commande HMMC, je vais regarder comment tu l’a mise en place.
Pour le mode transparent, je l’avais fait LMMC, c’est un peut plus lent que HMMC.
aoineko
Membre non connecté
Conseiller Municipal
ericb59 :
Pour le mode transparent, je l’avais fait LMMC, c’est un peut plus lent que HMMC.
LMMC est surtout lent pour les modes 4-bits par couleur (comme les screen 5 et 7) et le mode 2-bits par couleur (comme le screen 6) car on doit envoyer 2 et 4 fois plus de data respectivement.
Metalion :
J'ai déjà eu ce problème ... Impossible de placer les tables au delà de 10000h, ça plantait.
Dans mon cas, c'était un bug dans mon code (un shift d'une mauvaise valeur).
Par contre, j'ai découvert un truc marrant.
Je pensais que les bit#7 à 9 de l'adresse de SAT devaient toujours être à 1 sur le V9938 pour que les sprites s'affichent.
C'est bien le cas du bit#9, mais les bits bit#7 et 8 ont un comportement différent ; ils semble modifier la façon dont est géré les couleurs des sprites.
En tout cas, en jouant avec des bits (pas de vilain jeu de mot ) on a des effets intéressants.
Je vais creuser la question pour voir si c'est exploitable ou pas.
On est toujours ignorant avant de savoir.
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie