La Place des Développeurs Première Mondiale : La première Rom avec Fusion-C !
aoineko
Membre non connecté
Conseiller Municipal
Reprise du message précédent
Yep, dans ce cas, le mieux est d'avoir des structures en mémoire qui correspondent à celle en VRAM et d'envoyer les données par paquet par HMMC (ou via l'écriture séquentielle).C'est du détail, mais pour tes 4 outi finaux, tu devrais faire le di juste avant le premier, et le ei juste avant le dernier pour limiter le temps ou tu désactives les interruptions. Depuis que je fais mumuse avec le HBlank, je me rends compte de l'importance de limiter au maximum les temps de désactivations des interruptions (mais ça vaut aussi pour la musique par ex.).
On est toujours ignorant avant de savoir.
aoineko
Membre non connecté
Conseiller Municipal
Tiens, je viens de découvrir un truc relou avec SDCC.
Dans certain cas, il génère du code anormalement lourd quand on accède à une variable globale.
Au lieu d'un simple :
33 cycles ou lieu de 13.
Heureusement, j'ai trouvé un moyen de l'obliger à généré le bon code : il "suffit" de dire au compilo que notre variable est une "valeur pointée par une adresse" et utiliser en C *((char*)&g_MyVar) plutôt que g_MyVar .
C'est un peu lourd à écrire (même encapsulé dans une macro), mais pour 20 cycles gagnés à chaque lecture de mes variables, je prends.
J'essaye de voir du coté de SDCC s'il y a une solution propre (notamment via le peephole) mais en attendant c'est mieux que rien.
Dans certain cas, il génère du code anormalement lourd quand on accède à une variable globale.
Code ASM :
ld iy, #_g_MyVar ; 14 cycles ld a, 0 (iy) ; 19 cycles
Au lieu d'un simple :
Code ASM :
ld a, (#_g_MyVar + 0) ; 13 cycles
33 cycles ou lieu de 13.
Heureusement, j'ai trouvé un moyen de l'obliger à généré le bon code : il "suffit" de dire au compilo que notre variable est une "valeur pointée par une adresse" et utiliser en C *((char*)&g_MyVar) plutôt que g_MyVar .
C'est un peu lourd à écrire (même encapsulé dans une macro), mais pour 20 cycles gagnés à chaque lecture de mes variables, je prends.
J'essaye de voir du coté de SDCC s'il y a une solution propre (notamment via le peephole) mais en attendant c'est mieux que rien.
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
aoineko :
Si [font= courier new]iy[/font] est réutilisé plus loin dans la fonction ça va faire un beau bug...
De toute façon avec SDCC 4.07 je ne suis pas certain que l'option --peep-file fonctionne
J'ai essayé avec ce fichier d'optimisation, mais je n'ai remarqué aucune différence avec ou sans ...
peep.txt
ericb59
Membre non connecté
Conseiller Municipal
J'ai aujourd'hui réussi à faire ma première Rom 48K avec Fusion-C
En fait, j'utilise exactement le même crt0 que pour la rom 32K
Dans mon code je force un bloc de données à se placer en 0x0000
Puis avec 2 routines ASM, j'échange la Page 0 que vois le Z80 soit avec le Bios, soit avec la page 0 de la ROM.
et vice versa ...
Par contre quand le Bios n'est pas présent, aucune interruption n'est permise.
Mais doit y avoir moyen de feinter Edité par ericb59 Le 16/12/2020 à 20h39
En fait, j'utilise exactement le même crt0 que pour la rom 32K
Dans mon code je force un bloc de données à se placer en 0x0000
Code C :
const unsigned char __at(0x00) datas[] = ...
Puis avec 2 routines ASM, j'échange la Page 0 que vois le Z80 soit avec le Bios, soit avec la page 0 de la ROM.
et vice versa ...
Par contre quand le Bios n'est pas présent, aucune interruption n'est permise.
Mais doit y avoir moyen de feinter Edité par ericb59 Le 16/12/2020 à 20h39
aoineko
Membre non connecté
Conseiller Municipal
A ma connaissance, la seule feinte possible c'est d'avoir le code d'interruption à l'adresse 0038h dans ta ROM.
Perso, pour ma ROM 48K, j'ai laissé la page 0 sur le Bios par défaut. Du coup, cette page de la ROM ne sert que pour stocker des datas.
Pour l'utiliser il faut :
- désactiver les interruptions,
- switch la page 0 sur la ROM,
- copier ce dont on a besoin en RAM,
- switch la page 0 sur le Bios,
- réactiver les interruptions,
- (copier les données RAM en VRAM si besoin).
C'est bien pour charger des graphismes au début d'un niveau par ex., mais c'est pas vraiment utilisable en plein gameplay.
Mais mon but à terme c'est de remplacer complètement le Bios (pour avoir un code d'interruption bcp plus léger et sans certains défauts de celui de base).
Quand ça sera fait, toutes mes ROM pourront commencer en page 0 (le code d'interruption sera placé en 0038h).
Perso, pour ma ROM 48K, j'ai laissé la page 0 sur le Bios par défaut. Du coup, cette page de la ROM ne sert que pour stocker des datas.
Pour l'utiliser il faut :
- désactiver les interruptions,
- switch la page 0 sur la ROM,
- copier ce dont on a besoin en RAM,
- switch la page 0 sur le Bios,
- réactiver les interruptions,
- (copier les données RAM en VRAM si besoin).
C'est bien pour charger des graphismes au début d'un niveau par ex., mais c'est pas vraiment utilisable en plein gameplay.
Mais mon but à terme c'est de remplacer complètement le Bios (pour avoir un code d'interruption bcp plus léger et sans certains défauts de celui de base).
Quand ça sera fait, toutes mes ROM pourront commencer en page 0 (le code d'interruption sera placé en 0038h).
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
aoineko :
A ma connaissance, la seule feinte possible c'est d'avoir le code d'interruption à l'adresse 0038h dans ta ROM.
Oui c'est bien à cela que je pensais.
Mais quel est le code à mettre dans la ROM ?
Une copie de la fonction KEYINT du bios ?
La commande KEYINT en 0x38 est en fait un
JP #0cx0c3c
Et à cet endroit on a toute une routine... qui fait je ne sais pas trop quoi... son travail... quoi...
Code ASM :
; Subroutine KEYINT ; Inputs ________________________ ; Outputs ________________________ ; Remark Entry at the same adres as MSX1 J0C3C: 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 CALL C1479 JP P,J0D02 CALL H.TIMI EI LD (STATFL),A AND 20H ; " " LD HL,TRPTBL+11*3 CALL NZ,C0EF1 LD HL,(INTCNT) DEC HL LD A,H OR L JR NZ,J0C73 LD HL,TRPTBL+17*3 CALL C0EF1 LD HL,(INTVAL) J0C73: LD (INTCNT),HL LD HL,(JIFFY) INC HL LD (JIFFY),HL LD A,(MUSICF) LD C,A XOR A J0C82: RR C PUSH AF PUSH BC CALL C,C1131 POP BC POP AF INC A CP 03H ; 3 JR C,J0C82 LD HL,SCNCNT DEC (HL) JR NZ,J0D02 IF INTHZ EQ 60 LD (HL),2 ; scanfrequency 2*1000/60 = 33 ms ELSE LD (HL),1 ; scanfrequency 1*1000/50 = 20 ms ENDIF XOR A CALL C1202 AND 30H ; "0" PUSH AF LD A,01H ; 1 CALL C1202 AND 30H ; "0" RLCA RLCA POP BC OR B PUSH AF CALL C121C AND 01H ; 1 POP BC OR B LD C,A LD HL,TRGFLG XOR (HL) AND (HL) LD (HL),C LD C,A RRCA LD HL,TRPTBL+12*3 CALL C,C0EF1 RL C LD HL,TRPTBL+16*3 CALL C,C0EF1 RL C LD HL,TRPTBL+14*3 CALL C,C0EF1 RL C LD HL,TRPTBL+15*3 CALL C,C0EF1 RL C LD HL,TRPTBL+13*3 CALL C,C0EF1 XOR A LD (CLIKFL),A CALL C0D12 JR NZ,J0D02 LD HL,REPCNT DEC (HL) JR NZ,J0D02 LD (HL),1 LD HL,OLDKEY+0 LD DE,OLDKEY+1 LD BC,11-1 LD (HL),0FFH LDIR CALL C0D4E J0D02: POP IX POP IY POP AF POP BC POP DE POP HL EX AF,AF' EXX POP AF POP BC POP DE POP HL EI RET
Je vais essayer de mettre ca dans ma page 0 de ROM 48K, pour voir si ca continue de faire tourner les interruptions.
Je suis bien conscient que tout ceci à déjà été questionné, pensé, réfléchi, plus ou moins expliqué depuis belle lurette... Mais comme on ne trouve pas de document clair et précis sur "comment c'est t'y qu'on fait"... et bien on ré-invente la roue à chaque curieux qui veut mettre les pieds dans le plat
Edité par ericb59 Le 17/12/2020 à 11h07
aoineko
Membre non connecté
Conseiller Municipal
Voici un pseudo code d'après les infos fournis par Grauw sur son site :
Le problème c'est qu'il y a plein de call qui sont fait à partir de ce code vers du code situé ailleurs.
Il faudrait donc embarquer tout ces bouts de code à leur bonne adresse.
C'est pas impossible, mais de toute façon, perso, je préfère largement avoir mon propre code optimisé pour les jeux.
(et ça évitera quelques incohérences qu'on est obligé d'avoir dans nos libs à cause de ce code d'interruption par défaut comme le fait de devoir toujours reset le registre VDP de status à 0)
Code TEXT :
- Stack all registers - Invoke H.KEYI hook - Read VDP status register S#0 if(Turbo R) - Check PAUSE key - Check VDP interrupt if(VDP interrupt) - Invoke H.TIMI hook - Enable Interrupts (EI) - Save S#0 in STATFL - ON INTERVAL GOSUB - Increase TIME variable (JIFFY) - Handle PLAY if(JIFFY % 2 == 0) // Every second VDP interrupt - Keyboard scan - Processing keys - ON STRIG GOSUB - Key repetition - Restore all registers - Enable Interrupts (EI) - RETurn from Interrupt (RETI)
Le problème c'est qu'il y a plein de call qui sont fait à partir de ce code vers du code situé ailleurs.
Il faudrait donc embarquer tout ces bouts de code à leur bonne adresse.
C'est pas impossible, mais de toute façon, perso, je préfère largement avoir mon propre code optimisé pour les jeux.
(et ça évitera quelques incohérences qu'on est obligé d'avoir dans nos libs à cause de ce code d'interruption par défaut comme le fait de devoir toujours reset le registre VDP de status à 0)
On est toujours ignorant avant de savoir.
ericb59
Membre non connecté
Conseiller Municipal
Oui j’ai passé une grosse partie de la journée à décortiquer cette partie du Bios, et à rassembler toutes les sous routines qui vont avec l’interruption... c’est du boulot !!
Après on est sans doute pas obligé de. Gérer toutes les routines, comme celles de la Fonction Play et du clavier.
Pour le reste de ton commentaire, j’ai du mal à concevoir que tu veuille remplacer le Bios par tes propres routines. C’est un boulot dingue
J’imagine que si c’est efficace, quelqu’un d’autre aura déjà expérimenté la chose ?
J’ai toujours lu ici et ailleurs que pour préserver la compatibilité du code avec tous les MSX il fallait utiliser le Bios.
J’ai même eu des réflexions (pas désobligeantes) sur les routines hors Bios de Fusion-c que j’ai implantées ici ou là , alors que l’equivalent existait dans le Bios...
Quid ? Edité par ericb59 Le 17/12/2020 à 17h37
Après on est sans doute pas obligé de. Gérer toutes les routines, comme celles de la Fonction Play et du clavier.
Pour le reste de ton commentaire, j’ai du mal à concevoir que tu veuille remplacer le Bios par tes propres routines. C’est un boulot dingue
J’imagine que si c’est efficace, quelqu’un d’autre aura déjà expérimenté la chose ?
J’ai toujours lu ici et ailleurs que pour préserver la compatibilité du code avec tous les MSX il fallait utiliser le Bios.
J’ai même eu des réflexions (pas désobligeantes) sur les routines hors Bios de Fusion-c que j’ai implantées ici ou là , alors que l’equivalent existait dans le Bios...
Quid ? Edité par ericb59 Le 17/12/2020 à 17h37
aoineko
Membre non connecté
Conseiller Municipal
A partir du moment ou tu utilises directement le PPI, le VDP et le PSG via les ports, tu n'es déjà plus dans l'utilisation "pure" du Bios.
D'un autre coté, à priori, il n'y a aucun cas d'incompatibilité connu à utiliser ces périphériques sans passer par le Bios (à part une obscure carte graphique MSX2 pour les MSX1 brésilien).
Du coup, la question pourrait plutôt être « pourquoi utiliser le Bios ? ».
Ca peut avoir du sens dans l'approche généraliste de ta lib, mais pour moi qui ne m'intéresse qu'aux jeux, je n'ai aucun besoin du Bios (les accès via les ports sont suffisants).
Au contraire, il prends des ressources (RAM et temps CPU) que je veux récupérer pour mes jeux.
Et pour en revenir au code d'interruption, la version que je compte faire ne sera pas compliqué car... elle ne fera que ce dont j'ai besoin.
Dans un premier temps, elle ne gérera que les V-Blank et les H-Blank (je préfère gérer les inputs clavier/joystick coté jeu).
La où ça deviendra plus coton, c'est quand je m'attaquerai à la gestion du disque.
Mais pour le moment j'en ai pas besoin et de toute façon, les ROM du MSX sont toujours accessibles via les accès inter-slot si besoin.
D'un autre coté, à priori, il n'y a aucun cas d'incompatibilité connu à utiliser ces périphériques sans passer par le Bios (à part une obscure carte graphique MSX2 pour les MSX1 brésilien).
Du coup, la question pourrait plutôt être « pourquoi utiliser le Bios ? ».
Ca peut avoir du sens dans l'approche généraliste de ta lib, mais pour moi qui ne m'intéresse qu'aux jeux, je n'ai aucun besoin du Bios (les accès via les ports sont suffisants).
Au contraire, il prends des ressources (RAM et temps CPU) que je veux récupérer pour mes jeux.
Et pour en revenir au code d'interruption, la version que je compte faire ne sera pas compliqué car... elle ne fera que ce dont j'ai besoin.
Dans un premier temps, elle ne gérera que les V-Blank et les H-Blank (je préfère gérer les inputs clavier/joystick coté jeu).
La où ça deviendra plus coton, c'est quand je m'attaquerai à la gestion du disque.
Mais pour le moment j'en ai pas besoin et de toute façon, les ROM du MSX sont toujours accessibles via les accès inter-slot si besoin.
On est toujours ignorant avant de savoir.
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie