La Place des Développeurs Projet Carwar
aoineko
Membre non connecté
Conseiller Municipal
Reprise du message précédent
Le but est de faire un jeu qui soit utilisable par le plus grand nombre de fans de MSX dans le monde.Je sais bien qu'en passant à 60Hz la frame dure moins longtemps et que cela réduit donc les perfs/frame pour le CPU et le GPU. Mais si c'est la meilleure solution pour qu'un maximum de personnes puissent profiter du jeu, je trouverai une solution.
En fait, ce qui n'est pas clair, c'est les relations entre la fréquence d'affichage native du MSX, la fréquence modifié en soft et la fréquence du moniteur.
On est toujours ignorant avant de savoir.
aoineko :
En fait, ce qui n'est pas clair, c'est les relations entre la fréquence d'affichage native du MSX, la fréquence modifié en soft et la fréquence du moniteur
Il n'y a pas de fréquence native du MSX ...
La seule fréquence du MSX est celle déterminée par le VDP à travers le registre dédié.
Ensuite, soit le moniteur a une fréquence fixe, soit il s'adapte à celle qu'il reçoit par le signal vidéo.
Metalion :
PS : Je ne suis pas sur que le fait de basculer le VDP à 60Hz fait également basculer le mode de codification de l'image (NTSC ou PAL) qui est autrement plus complexe que la simple fréquence. Autrement dit, je me demande si sur les MSX européens, on ne fait en fait que basculer entre du PAL 50Hz et du PAL 60Hz ...
Après avoir fait quelques recherches dans la doc Yamaha sur le VDP 9938, je pense que je peux préciser la question du standard vidéo.
En fait, le VDP ne sort que des signaux RGB et une fréquence de synchronisation. Tout autre traitement vidéo est donc fait en dehors du VDP, sur la carte mère de l'ordinateur. Etant donné que les systèmes PAL et NTSC sont en fait des normes de modulation et de combinaison des signaux RGB d'origine, cela signifie donc que l'émission d'une image au standard PAL ou NTSC dépend de l'origine de l'ordinateur et non pas du VDP.
En clair, si l'image est transmise au moniteur/téléviseur à travers les signaux RGB, il n'y a aucun souci de standard.
En revanche, si l'image est transmise à travers une connexion composite (CVBS ou S-Vidéo), le signal sera envoyé selon le standard de la machine (PAL pour les MSX européens, NTSC pour les MSX japonais), quelle que soit la fréquence du VDP (50Hz ou 60Hz).
On peut donc générer uniquement du PAL 50Hz/60Hz sur les MSX européens, et du NTSC 50Hz/60Hz sur les MSX japonais.
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 :
Il n'y a pas de fréquence native du MSX ...
La seule fréquence du MSX est celle déterminée par le VDP à travers le registre dédié.
Ensuite, soit le moniteur a une fréquence fixe, soit il s'adapte à celle qu'il reçoit par le signal vidéo.
La seule fréquence du MSX est celle déterminée par le VDP à travers le registre dédié.
Ensuite, soit le moniteur a une fréquence fixe, soit il s'adapte à celle qu'il reçoit par le signal vidéo.
Ce que j'appelle la fréquence native, c'est la valeur du registre VDP au démarrage (qui n'est pas la même sur un MSX japonais ou européen).
Faudra que je contact des fans de MSX japonais pour savoir comment ils se débrouillent avec les jeux 50Hz.
EDIT : Remarque, y a la solution de faire 2 versions (50/60) et/ou de laisser choisir dans les options du jeu. Edité par aoineko Le 30/03/2011 à 17h56
On est toujours ignorant avant de savoir.
aoineko :
Faudra que je contact des fans de MSX japonais pour savoir comment ils se débrouillent avec les jeux 50Hz.
EDIT : En relisant, je me suis rendu compte que tu ne parlais pas de programmation mais d'utilisation. Les japonais avaient le même problème que nous sauf que là-bas, les TV multi-standard ont toujours été rares donc, il y avait moins de TV qui supportent le 50 Hz que de TV qui supportent le 60Hz en Europe. De nos jours, les TV numériques à écran plat ont pris le relais donc il serait interessant de savoir si elles supportent le 50 Hz en effet. Edité par GDX Le 01/04/2011 à 06h57
aoineko
Membre non connecté
Conseiller Municipal
Bon, je crash dès que j'essaye de setter mon hook de VBLANK.
Si un pro du ASM peut se pencher sur la question, ça se passe ci-dessous.
La fonction SetHook prend 2 paramètres : l'adresse du hook (ix 4-5) et l'adresse de la fonction vers laquelle sauté (ix 6-7).
Si la fonction est égal à 0, on set un ret.
Sinon, on set un jump vers la fonction.
Pour mes testes, je passe la fonction ci-dessous... qui ne fait qu'un return.
Une idée ?
Si un pro du ASM peut se pencher sur la question, ça se passe ci-dessous.
La fonction SetHook prend 2 paramètres : l'adresse du hook (ix 4-5) et l'adresse de la fonction vers laquelle sauté (ix 6-7).
Si la fonction est égal à 0, on set un ret.
Sinon, on set un jump vers la fonction.
Code ASM :
_SetHook: pushix ldix,#0 addix,sp lda,6 (ix) ora,7 (ix) jrNZ,00102$ ldl,4 (ix) ldh,5 (ix) ld(hl),#0xC9 jr00104$ 00102$: ldl,4 (ix) ldh,5 (ix) ld(hl),#0xC3 inc4 (ix) jrNZ,00107$ inc5 (ix) 00107$: ldl,4 (ix) ldh,5 (ix) lda,6 (ix) ld(hl),a inchl lda,7 (ix) ld(hl),a 00104$: popix ret
Pour mes testes, je passe la fonction ci-dessous... qui ne fait qu'un return.
Code ASM :
_VBlankInterrupt: ret
Une idée ?
On est toujours ignorant avant de savoir.
Peux-tu écrire ton programme en opcodes standard STP ?
http://www.gaby.de/z80/z80sean.txt
http://fms.komkon.org/MSX/Docs/Z80-1.txt
Pour que ton programme soit cadencé à peu près de la même façon en 50 Hz qu'en 60 Hz, tu peux faire un compteur et une condition afin de sauter ta routine 1 frame sur 5 en mode 60 Hz. Edité par GDX Le 01/04/2011 à 04h22
http://www.gaby.de/z80/z80sean.txt
http://fms.komkon.org/MSX/Docs/Z80-1.txt
Pour que ton programme soit cadencé à peu près de la même façon en 50 Hz qu'en 60 Hz, tu peux faire un compteur et une condition afin de sauter ta routine 1 frame sur 5 en mode 60 Hz. Edité par GDX Le 01/04/2011 à 04h22
Le code généré par ton compilateur est vraiment très pénible
Non seulement il use et abuse de l'adressage indirect par IX ...
Ce qui pénalise fortement la vitesse d'éxécution est la lisibilité ...
Mais en plus il génère un code qui n'est pas conforme à la syntaxe standard du Z80
Notamment, je suppose que l'instruction "ld a,5 (ix)" est en fait "ld a,(ix+5)" en syntaxe correcte ...
Sinon : pendant toute modification du hook, il faut bien évidemment arrêter toute interruption, donc :
A part cela, je ne voit pas d'autre problème, mais il faut bien dire (même si je me répète) que ton code est obtus ...
Non seulement il use et abuse de l'adressage indirect par IX ...
Ce qui pénalise fortement la vitesse d'éxécution est la lisibilité ...
Mais en plus il génère un code qui n'est pas conforme à la syntaxe standard du Z80
Notamment, je suppose que l'instruction "ld a,5 (ix)" est en fait "ld a,(ix+5)" en syntaxe correcte ...
Sinon : pendant toute modification du hook, il faut bien évidemment arrêter toute interruption, donc :
Code :
di
...
(ton code)
..
ei
A part cela, je ne voit pas d'autre problème, mais il faut bien dire (même si je me répète) que ton code est obtus ...
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)
Je suis plus pour la solution de GDX.
Dans le zip du crossassembler asmsx v.0.12 g, le modèle de MineSweeper donne un bon exemple de ce qui peut être fait pour la détection du type de MSX et de sa fréquence et la gestion pour un compteur mais on peut l'utiliser de bien d'autres façon (voir post précédent)...
Dans le zip du crossassembler asmsx v.0.12 g, le modèle de MineSweeper donne un bon exemple de ce qui peut être fait pour la détection du type de MSX et de sa fréquence et la gestion pour un compteur mais on peut l'utiliser de bien d'autres façon (voir post précédent)...
Code ASM :
;--------------------------------------------------------- ; CONSTANTS ;--------------------------------------------------------- ; VRAM addresses CHRTBL equ 0000h NAMTBL equ 1800h CLRTBL equ 2000h SPRTBL equ 3800h SPRATR equ 1B00h ; BIOS routine - Turbo-R computers only! SETCPU equ 0180h ; Constantes de la BIOS MSXID1 equ 002bh MSXID3 equ 002dh ; System variables addresses CLIKSW equ 0f3DBh ; Keyboard click sound FORCLR equ 0f3e9h ; Foreground colour RG9SAV equ 0ffe8h ; V9938 register copy ;---------------------------------------------------------- ; ; ; ;---------------------------------------------------------- INITIALISATION: ; All previous initialization processes ;---------------------------------------------------------- ; Sets R register to range 0-127 xor a ld r,a ; Silent key click ld [CLIKSW],a ; If Turbo-R is detected, switch to Z80 mode ld a,[MSXID3] cp 3 jr nz,@@DONE ld a,$80 call SETCPU @@DONE: ; Determines screen frequency ld b,60 ld a,[MSXID3] or a jr nz,@@MSX2 ; First generation MSX ld a,[MSXID1] rla jr nz,@@OK ld b,50 jr @@OK ; MSX2 or higher (V9938/V9958) @@MSX2: ld a,[RG9SAV] and $02 jr z,@@OK ld b,60 ; Store frequency @@OK: ld a,b ld [FREQUENCY],a ; Desactivate clock call CLOCK_STOP ; Install interruption routine ld hl,$fd9f ld bc,INTERRUPTION ld [hl],$c3 inc hl ld [hl],c inc hl ld [hl],b ; ; ; ;---------------------------------------------------------- INTERRUPTION: ;---------------------------------------------------------- push af push bc push de push hl call CLOCK_UPDATE pop hl pop de pop bc pop af ret ;---------------------------------------------------------- ; ; ; ;---------------------------------------------------------- CLOCK_UPDATE: ; Updates clock if necesary ;---------------------------------------------------------- ; Test if clock is on ld a,[CLOCK] or a ret z ; Adjust frame counter ld hl,COUNTER inc [hl] ; If equal to frequency, update clock ld a,[FREQUENCY] cp [hl] ret nz ; Init frame counter to zero xor a ld [hl],a ; Increase seconds ld a,[SECONDS] add 01h daa ld [SECONDS],a cp 60h jr nz,@@UPDATE ; Increase minutes xor a ld [SECONDS],a ld a,[MINUTES] add 01h daa ld [MINUTES],a @@UPDATE: ; Convert BCD variables to ASCII text ld a,[SECONDS] call BCD_TO_ASCII ld hl,TIMER+4 ld [hl],e dec hl ld [hl],d ld a,[MINUTES] call BCD_TO_ASCII ld hl,TIMER+1 ld [hl],e dec hl ld [hl],d ; Print text ld hl,TIMER ld de,NAMTBL+25 ld bc,5 call LDIRVM ret ;----------------------------------------------------------
Le MSXien le plus à l'ouest ... ou presque
aoineko
Membre non connecté
Conseiller Municipal
Si j'avais fait le jeu en assembleur, j'en serai encore à essayer de faire bouger mes sprites.
Et puis, l'avantage du C++, c'est qu'on peut mixer avec du code ASM pour les parties les plus importantes.
Pour en revenir a mon programme, je vais essayer de setter le hook en dur en ASM avec les adresses du hook et de la fonction directement dans le code ; je verrai bien si le problème viens de ma fonction qui set le hook ou bien du hook en lui même (même si, étant vide, je vois pas comment il pourrait poser problème ).
Pour la fréquence, elle est setté en dur à 60Hz via le code ; je vais laisser comme ça.
Et puis, l'avantage du C++, c'est qu'on peut mixer avec du code ASM pour les parties les plus importantes.
Pour en revenir a mon programme, je vais essayer de setter le hook en dur en ASM avec les adresses du hook et de la fonction directement dans le code ; je verrai bien si le problème viens de ma fonction qui set le hook ou bien du hook en lui même (même si, étant vide, je vois pas comment il pourrait poser problème ).
Pour la fréquence, elle est setté en dur à 60Hz via le code ; je vais laisser comme ça.
On est toujours ignorant avant de savoir.
aoineko
Membre non connecté
Conseiller Municipal
Mon compteur de seconde par interruption VBlank fonctionne ; par contre il lag un peu.
Je me demandais ; que ce passe t'il si un VBlank interviens alors qu'une instruction di est en cours ?
Il attend un ei ou l'interruption est perdu ?
S'il est perdu, ça expliquerai peut être le lag. Edité par aoineko Le 04/04/2011 à 01h05
Je me demandais ; que ce passe t'il si un VBlank interviens alors qu'une instruction di est en cours ?
Il attend un ei ou l'interruption est perdu ?
S'il est perdu, ça expliquerai peut être le lag. Edité par aoineko Le 04/04/2011 à 01h05
On est toujours ignorant avant de savoir.
Dans le cas où une IRQ arrive sur le bus du Z80, si l'opération DI a été exécutée, l'interruption est perdue.
D'où l'intérêt de limiter les phases DI/EI au strict minimum (voire même à anticiper l'EI d'une instruction).
Ceci dit, sauf si ton code est truffé de phases DI/EI, tu ne devrais pas voir de modification sur ton compteur. J'ai un jeu en développement, qui contient des phases DI/EI normales (pour les accès VDP et VRAM), et qui utilise un compteur en secondes basé sur l'utilisation du hook en $FD9F, et je ne vois aucune perturbation visible ...
D'où l'intérêt de limiter les phases DI/EI au strict minimum (voire même à anticiper l'EI d'une instruction).
Ceci dit, sauf si ton code est truffé de phases DI/EI, tu ne devrais pas voir de modification sur ton compteur. J'ai un jeu en développement, qui contient des phases DI/EI normales (pour les accès VDP et VRAM), et qui utilise un compteur en secondes basé sur l'utilisation du hook en $FD9F, et je ne vois aucune perturbation visible ...
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
J'ai implémenté une nouvelle compression sur mes sprites qui m'a fait gagné 5 Ko !!
De toute façon, j'avais plus le choix, sinon il y avait plus la place sur ma cartouche 32Ko pour mettre le code pour finir le jeu.
Pour ceux que ça intéresse, la compression s'appuie sur l'élimination des 0 (transparence) qui pullulent dans les sprites.
En Y, je calculs la première et dernière ligne contenant un point non transparent et je stock l'info sur 1 octet sous la forme [offset Y|taille Y].
Par exemple, si un sprite 13x11 de voiture à l'horizontal commence et fini par 3 ligne complétement transparentes. Je commence donc par un octet = [3|5].
Ensuite, je fais de même avec X pour chaque ligne. Elle commence donc toujours par un octet du type [offset X|taille X] suivi des données comprises entre ces bornes.
Avec cette compression, mon premier sprite passe de 143 octets (13x11) à 77 octets ; soit 50% de compression.
J'ai encore une solution de compression en créant une palette de 16 couleurs par sprite et en codant chaque point sur 4 bits... mais bon, pour l'instant, je vais me contenter de mes 5 Ko gagné.
De toute façon, j'avais plus le choix, sinon il y avait plus la place sur ma cartouche 32Ko pour mettre le code pour finir le jeu.
Pour ceux que ça intéresse, la compression s'appuie sur l'élimination des 0 (transparence) qui pullulent dans les sprites.
En Y, je calculs la première et dernière ligne contenant un point non transparent et je stock l'info sur 1 octet sous la forme [offset Y|taille Y].
Par exemple, si un sprite 13x11 de voiture à l'horizontal commence et fini par 3 ligne complétement transparentes. Je commence donc par un octet = [3|5].
Ensuite, je fais de même avec X pour chaque ligne. Elle commence donc toujours par un octet du type [offset X|taille X] suivi des données comprises entre ces bornes.
Avec cette compression, mon premier sprite passe de 143 octets (13x11) à 77 octets ; soit 50% de compression.
J'ai encore une solution de compression en créant une palette de 16 couleurs par sprite et en codant chaque point sur 4 bits... mais bon, pour l'instant, je vais me contenter de mes 5 Ko gagné.
On est toujours ignorant avant de savoir.
GuillianSeed
Membre non connecté
Villageois
Bravo !!
Il n'y a pas que dans la rénovation que le système D compte beaucoup !!
Bonne continuation Aoineko ! Et j'espère voir Carwar dans le MSXDev !!!!!!
Il n'y a pas que dans la rénovation que le système D compte beaucoup !!
Bonne continuation Aoineko ! Et j'espère voir Carwar dans le MSXDev !!!!!!
aoineko
Membre non connecté
Conseiller Municipal
Je pense le présenter au MSXDev en hors catégorie.
Si ça peut leur donner envi de faire dans le future un concourt MSX2 en plus de celui pour MSX1, ça serait cool.
Si ça peut leur donner envi de faire dans le future un concourt MSX2 en plus de celui pour MSX1, ça serait cool.
On est toujours ignorant avant de savoir.
aoineko
Membre non connecté
Conseiller Municipal
Après le chargement d'un fichier depuis la disquette, le jeu se met dans une boucle infini.
J'ai essayé de tracer le code ASM, mais je vois pas ce qui se passe.
Mes variables en RAM ne semble pas écrasé par le BLTVD (file2vram copy), mais le flow ne reprend pas normalement.
Au cas ou qq'un peut y jeter œil, voici le code :
carwar_prb_infiniteLoop.zip
J'ai essayé de tracer le code ASM, mais je vois pas ce qui se passe.
Mes variables en RAM ne semble pas écrasé par le BLTVD (file2vram copy), mais le flow ne reprend pas normalement.
Au cas ou qq'un peut y jeter œil, voici le code :
carwar_prb_infiniteLoop.zip
On est toujours ignorant avant de savoir.
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie